Zig Programming Tutorial - ep001 - Intro

in dev •  9 months ago 

Zig Programming Tutorial - ep001 - Intro

zig.png

"Learn Zig Programming" Tutorial Series

Hello everybody. This is the first episode/post in my new series "Learn Zig Programming", which is a tutorial series about the Zig programming language. The idea here is to incrementally post about specific language topics, more or less in the same fashion as I used to do a few years ago with my Learn Python Series, with the remark that I am also writing this Zig tutorial series as an exercise / muscle memory builder / reminder for myself (as I am still learning Zig): Zig is a relatively new systems programming language which I am currently learning. It hasn't even reached the v.1.0 stage yet, and as the language itself is in a state of rapid development - often with breaking changes - there currently is a lack of (written) tutorial materials. I found that carefully writing these programming tutorials helps me to better grok a programming concept, with the added benefit of potentially helping others to learn (specific topics about) the Zig programming language as well.

So let's dive right in, shall we!

What is Zig?

Zig is a system programming language that aims to rival C in terms of efficiency and control, while introducing several modern features to improve safety and maintainability. One of Zig's key strengths is its seamless compatibility with C libraries and toolchains. This compatibility allows developers to easily integrate Zig into existing C projects or leverage C libraries in Zig programs. Zig's compatibility with the C ABI (Application Binary Interface) ensures that calling C functions from Zig code is straightforward and efficient. This interoperability extends to not only utilizing C libraries but also enabling Zig code to be called from C, making Zig a versatile tool for extending and improving existing C projects.

Unlike many modern languages that favor object-oriented paradigms, Zig primarily focuses on procedural programming. This focus aligns well with its goals of providing fine-grained control over low-level operations, a crucial aspect for system-level programming.

Zig also differentiates itself through its approach to error handling and memory safety. It avoids hidden control flow and automatic memory allocations, requiring developers to explicitly manage these aspects.

Key differences with other systems programming languages

Zig, compared to Rust, C++, and Nim, has distinct characteristics that set it apart in the realm of system programming:

  1. Rust: While Rust emphasizes safety and concurrency through its ownership model and borrow checker, Zig opts for simplicity and control, offering manual memory management without hidden control flow or memory allocations. Rust's approach aims to prevent memory and concurrency errors at compile time, whereas Zig focuses on giving the programmer complete control with an emphasis on explicit error handling and simpler language constructs.

  2. C++: Zig positions itself as a simpler and more straightforward alternative to C++. While C++ is known for its extensive features like object-oriented programming, templates, and operator overloading, Zig maintains a minimalistic design. Zig avoids complex features like exceptions and runtime polymorphism, focusing instead on compile-time execution and offering a leaner, more predictable development experience.

  3. Nim: Nim can be considered a higher-level language compared to Zig, even tho Nim can also run on microcontrollers, with features like garbage collection, high-level data types, and a Python-like syntax. In contrast, Zig sticks closer to the low-level nature of C, emphasizing manual memory management. Both target procedural programming. Nim aims to offer a balance between performance, elegance, and ease of use, while Zig prioritizes giving the programmer explicit control over every aspect of the program.

Notable Zig projects

Even tho Zig is a very young programming language, still a few successful high profile projects have been built with it, among which:

  • Bun: a very high performant JavaScript & Typescript toolkit and runtime, a NodeJS competitor but much faster because of being written in Zig;
  • TigerBeetle the world's fastest and yet smallest financial accounting database (I haven't done the actual benchmarks myself to verify this website claim, to see if it is indeed the fastest, yet it is extremely performant).

Installing Zig

To install Zig on your system, you can go to the Zig downloads page , grab the bundle for your OS, extract it, add a PATH to call zig from anywhere, or (as I did) install Zig using a package manager such as Homebrew on MacOS, via the command brew install zig

After having sourced your PATH, if running zig version outputs to the terminal console something like 0.11.0 (or whatever the current stable version is when you are reading this tutorial), you're good to go! :-)

Hello world!

Now that we have installed Zig and have a very shallow idea what it can do, let's create a new project folder ./hello-zig/ somewhere on your system ....

cd ~/Documents/dev/
mkdir hello-zig && cd ./hello-zig

.. and then inside that folder create a blank main.zig file (even tho it can be named anything you want with the .zig extension)

touch main.zig

Then open the main.zig file in your favorite text editor, paste in this code and save the file.

// import the Zig standard library
const std = @import("std");

// Create an alias 'print' to refer
// directly to the debug print function
// in the std.debug namespace
const print = std.debug.print;

// Entry point
pub fn main() void { // `void` means nothing is returned
    // ** is an array repeat expression, 25 times
    const divider = "=" ** 25;

    // {s} is the string format placeholder
    // The . before {divider} is an inline anonymous array
    // (or struct) initialization, as the second argument to the
    // `print()` function.
    print("{s}\n", .{divider});
    print("Hello {s}!\n", .{"world"});
    print("{s}\n", .{divider});
}

Nota bene: I've added some inline single-line comments beginning with // inside the program, explaining line by line what is happening.

Then run the following command from your terminal, assuming you're still inside the ./hello-zig/ folder:

zig run ./main.zig

If all goes well, your first Zig program will compile and then this output will be shown:

=========================
Hello world!
=========================

Congrats! ;-)

What's next?

We've only scratched the absolute tippy-top of the surface of the Zig programming language, but hopefully by now you're aware Zig exists, have a basic idea of what it is, what it can do, and how it sits within other programming languages, we've installed Zig (0.11 as of now) on your system, and we've compiled and ran a traditional "Hello world" example (with a few minor tweaks).

In the next episodes we'll further dive into specific language features topic by topic to ensure we properly understand everything and lay a proper foundation to build upon.
I hope you've enjoyed this tutorial episode and see you in the next one!

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE BLURT!