Zig Basic Syntax

This chapter introduces the basic syntax rules of the Zig language, laying a solid foundation for subsequent learning.

Program Structure

The Simplest Zig Program

const std = @import("std");

pub fn main() void {
    std.debug.print("Hello, World!\n", .{});
}

Let's analyze each part of this program:

  • const std = @import("std"); - Import the standard library
  • pub fn main() void - Define a public main function with void return type
  • std.debug.print() - Call the standard library's print function
  • .{} - Empty parameter tuple

Comments

Single-line Comments

// This is a single-line comment
const x = 42; // End-of-line comment

Documentation Comments

/// This is a documentation comment, used for generating documentation
/// Can span multiple lines
pub fn add(a: i32, b: i32) i32 {
    return a + b;
}

Top-level Documentation Comments

//! This is a top-level documentation comment
//! Used to describe the entire file or module

Identifiers

Naming Rules

  • Start with a letter or underscore
  • Can contain letters, numbers, underscores
  • Case-sensitive
const valid_name = 1;
const ValidName = 2;
const _private = 3;
const name123 = 4;

Naming Conventions

// Variables and functions: snake_case
const my_variable = 42;
fn my_function() void {}

// Types: PascalCase
const MyStruct = struct {};
const MyEnum = enum {};

// Constants: SCREAMING_SNAKE_CASE
const MAX_SIZE = 1024;

Keywords

Zig keywords cannot be used as identifiers:

// Control flow
if, else, switch, while, for, break, continue, return

// Type-related
struct, enum, union, fn, var, const, comptime

// Error handling
try, catch, error, defer, errdefer

// Others
pub, export, extern, inline, noinline, packed, align
and, or, null, undefined, unreachable, async, await, suspend, resume

Statements and Expressions

Statements

Statements perform operations but don't return values:

const x = 42;        // Declaration statement
var y: i32 = 10;     // Declaration statement
y = 20;              // Assignment statement

Expressions

Expressions evaluate and return values:

const sum = 1 + 2;           // Arithmetic expression
const is_equal = x == y;     // Comparison expression
const result = if (x > 0) 1 else 0;  // Conditional expression

Semicolon Rules

Semicolons are optional in Zig, but there are specific rules:

// Cases where semicolons are not needed
const x = 42
const y = 24

// Cases where semicolons are needed (multiple statements on same line)
const a = 1; const b = 2;

// Usually no semicolon needed after function calls
std.debug.print("Hello\n", .{})

Code Blocks

Use curly braces {} to define code blocks:

pub fn main() void {
    // This is a code block
    const x = 42;

    if (x > 0) {
        // This is another code block
        std.debug.print("Positive\n", .{});
    }
}

Operators

Arithmetic Operators

const a = 10;
const b = 3;

const sum = a + b;      // Addition: 13
const diff = a - b;     // Subtraction: 7
const product = a * b;  // Multiplication: 30
const quotient = a / b; // Division: 3
const remainder = a % b; // Modulus: 1

Comparison Operators

const x = 10;
const y = 20;

const equal = x == y;        // Equal: false
const not_equal = x != y;    // Not equal: true
const less = x < y;          // Less than: true
const less_equal = x <= y;   // Less than or equal: true
const greater = x > y;       // Greater than: false
const greater_equal = x >= y; // Greater than or equal: false

Logical Operators

const a = true;
const b = false;

const and_result = a and b;  // Logical AND: false
const or_result = a or b;    // Logical OR: true
const not_result = !a;       // Logical NOT: false

Bitwise Operators

const x: u8 = 0b1010; // 10
const y: u8 = 0b1100; // 12

const and_bits = x & y;   // Bitwise AND: 0b1000 (8)
const or_bits = x | y;    // Bitwise OR: 0b1110 (14)
const xor_bits = x ^ y;   // Bitwise XOR: 0b0110 (6)
const not_bits = ~x;      // Bitwise NOT: 0b11110101 (245)
const left_shift = x << 1; // Left shift: 0b10100 (20)
const right_shift = x >> 1; // Right shift: 0b0101 (5)

Literals

Integer Literals

const decimal = 42;          // Decimal
const binary = 0b101010;     // Binary
const octal = 0o52;          // Octal
const hex = 0x2A;            // Hexadecimal
const with_underscores = 1_000_000; // Using underscores as separators

Float Literals

const float1 = 3.14;         // Regular float
const float2 = 1.23e-4;      // Scientific notation
const float3 = 0x1.fp+1023;  // Hexadecimal float

Character Literals

const char = 'A';            // Character literal
const unicode = '中';        // Unicode character
const escape = '\n';         // Escape character

String Literals

const string = "Hello, World!";
const multiline =
    \\This is a
    \\multiline string
    \\using \\ prefix
;
const unicode_string = "你好,世界!";

Escape Sequences

const newline = '\n';        // Newline
const tab = '\t';            // Tab
const carriage_return = '\r'; // Carriage return
const backslash = '\\';      // Backslash
const quote = '\'';          // Single quote
const double_quote = '\"';   // Double quote
const null_char = '\0';      // Null character
const unicode = '\u{1F600}'; // Unicode escape

Array and Slice Literals

// Array literal
const array = [_]i32{1, 2, 3, 4, 5};
const explicit_array = [5]i32{1, 2, 3, 4, 5};

// String slice
const slice: []const u8 = "Hello";

Struct Literals

const Point = struct {
    x: f32,
    y: f32,
};

const point = Point{
    .x = 1.0,
    .y = 2.0,
};

// Simplified syntax (field names match variable names)
const x: f32 = 1.0;
const y: f32 = 2.0;
const point2 = Point{ x, y };

Function Call Syntax

// Basic function call
const result = add(1, 2);

// Method call syntax
const string = "hello";
const length = string.len;

// Chained calls
const processed = data.filter().map().collect();

Error Handling Syntax

// try expression
const file = try std.fs.cwd().openFile("data.txt", .{});

// catch expression
const value = parseNumber(input) catch 0;

// if error handling
if (parseNumber(input)) |num| {
    // Success case
    std.debug.print("Number: {}\n", .{num});
} else |err| {
    // Error case
    std.debug.print("Error: {}\n", .{err});
}

Optional Type Syntax

var maybe_number: ?i32 = null;
maybe_number = 42;

// if optional handling
if (maybe_number) |number| {
    std.debug.print("Number: {}\n", .{number});
} else {
    std.debug.print("No number\n", .{});
}

// orelse operator
const number = maybe_number orelse 0;

Compile-time Syntax

// comptime keyword
comptime var compile_time_var = 42;

// Compile-time function call
const result = comptime fibonacci(10);

// Compile-time condition
const is_debug = comptime std.debug.runtime_safety;

Code Example: Comprehensive Syntax Demonstration

const std = @import("std");

/// Calculate the sum of two numbers
pub fn add(a: i32, b: i32) i32 {
    return a + b;
}

/// Main function
pub fn main() void {
    // Variable declarations
    const x = 10;
    var y: i32 = 20;

    // Arithmetic operations
    const sum = add(x, y);
    const product = x * y;

    // Conditional expression
    const max = if (x > y) x else y;

    // String handling
    const message = "Calculation Results";

    // Output results
    std.debug.print("{}:\n", .{message});
    std.debug.print("Sum: {}\n", .{sum});
    std.debug.print("Product: {}\n", .{product});
    std.debug.print("Max: {}\n", .{max});

    // Loop
    var i: i32 = 0;
    while (i < 3) : (i += 1) {
        std.debug.print("Loop iteration {}\n", .{i});
    }
}

Syntax Best Practices

1. Maintain Consistent Indentation

// Good practice
if (condition) {
    doSomething();
    doAnotherThing();
}

// Avoid
if (condition) {
doSomething();
    doAnotherThing();
}

2. Reasonable Use of Blank Lines

const std = @import("std");

pub fn main() void {
    const x = 42;
    const y = 24;

    const sum = x + y;

    std.debug.print("Sum: {}\n", .{sum});
}

3. Appropriate Comments

// Explain complex logic
const hash = computeHash(data); // Using FNV-1a algorithm

/// Public APIs need documentation comments
pub fn processData(input: []const u8) ![]u8 {
    // Implementation details...
}

Summary

This chapter introduced Zig's basic syntax rules, including:

  • ✅ Program structure and comments
  • ✅ Identifiers and keywords
  • ✅ Operators and literals
  • ✅ Basic syntax structures
  • ✅ Code style recommendations

After mastering these basic syntax elements, you can start writing simple Zig programs. In the next chapter, we'll learn about variable declarations in Zig.