Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chapter 1 grammar and typos #145

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 24 additions & 24 deletions Chapters/01-zig-weird.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ This philosophy becomes clear with the following phrase from the official websit

> "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,
This phrase is especially 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.
Expand Down Expand Up @@ -75,9 +75,9 @@ behaviour in edge situations. Once again, less is more.
## Hello world in Zig

We 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
To start a new Zig project on 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
Just create a new directory on your computer, then, init a new Zig project
inside this directory, like this:

```bash
Expand Down Expand Up @@ -141,7 +141,7 @@ 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
They simply are scripts that describe the necessary steps to compile/build
your project.

However, these are separate tools, that do not
Expand Down Expand Up @@ -169,7 +169,7 @@ 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,
and it has a valid `build.zig.zon` file in the 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.

Expand Down Expand Up @@ -314,7 +314,7 @@ module is by default private to this Zig module and can only be called from with
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.
does 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.

Expand Down Expand Up @@ -707,7 +707,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 an 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.

Expand All @@ -734,7 +734,7 @@ Everytime you declare a new object in Zig, you have two choices:

To 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
When you assign an object to an underscore, like in the example below, the `zig` compiler will automatically
discard the value of this particular object.

You can see in the example below that, this time, the compiler did not
Expand Down Expand Up @@ -806,7 +806,7 @@ t.zig:7:5: note: consider using 'const'

## Primitive Data Types {#sec-primitive-data-types}

Zig have many different primitive data types available for you to use.
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 page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].

Expand Down Expand Up @@ -960,7 +960,7 @@ 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.
has 2 elements in it.

```{zig}
#| auto_main: true
Expand Down Expand Up @@ -1139,7 +1139,7 @@ if (x == 124 and y == 124) {



## How strings work in Zig? {#sec-zig-strings}
## How do strings work in Zig? {#sec-zig-strings}

The first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).
But in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.
Expand All @@ -1152,7 +1152,7 @@ In summary, there are two types of string values that you care about in Zig, whi

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
Therefore, a string literal value has a data type in the format `*const [n:0]u8`. The `n` in the data type
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,
Expand All @@ -1163,7 +1163,7 @@ 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.
It's worth to emphasize that the array of bytes in a string object is not null-terminated, like in a
It's worth emphasizing that the array of bytes in a string object is not null-terminated, like in a
string literal value.

```{zig}
Expand All @@ -1175,7 +1175,7 @@ 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
sequence of bytes you're working with, but it's not really Zig's job to fix the encoding of your strings
(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] 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.
Expand Down Expand Up @@ -1235,13 +1235,13 @@ the string inside the object itself. In the case of a string literal value, this
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'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.
"out of bounds", i.e., if you're 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.
where exactly the array ends, or, in other words, to find how many elements the array of bytes contains.

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:
Expand Down Expand Up @@ -1374,23 +1374,23 @@ to represent the number 570. That is why the relationship between bytes and unic
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
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
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
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.

In the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in
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:

Expand Down Expand Up @@ -1474,9 +1474,9 @@ try stdout.print(
);
```

The `concat()` function, as the name suggests, concatenate two or more strings together.
The `concat()` function, as the name suggests, concatenates 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
accommodate all the strings together, this `concat()` function receives an allocator
object as input.

```{zig}
Expand Down Expand Up @@ -1588,7 +1588,7 @@ also has some rules that help you to achieve another type of safety, which is mo
program logic safety. These rules are:

- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.
- switch statements must exaust all possible options.
- switch statements must exhaust all possible options.
- the `zig` compiler forces you to handle every possible error in your program.


Expand Down