~tieong/ziglings

967b96b1d6b975c9ef5acb46cf66153b3c621b50 — Thomas Ieong 2 years ago 8c264bc my-answers
The answers to the exercices.

The @compileLog builtin and the doc were very helpful.
91 files changed, 217 insertions(+), 183 deletions(-)

M exercises/001_hello.zig
M exercises/002_std.zig
M exercises/003_assignment.zig
M exercises/004_arrays.zig
M exercises/005_arrays2.zig
M exercises/006_strings.zig
M exercises/007_strings2.zig
M exercises/008_quiz.zig
M exercises/009_if.zig
M exercises/010_if2.zig
M exercises/011_while.zig
M exercises/012_while2.zig
M exercises/013_while3.zig
M exercises/014_while4.zig
M exercises/015_for.zig
M exercises/016_for2.zig
M exercises/017_quiz2.zig
M exercises/018_functions.zig
M exercises/019_functions2.zig
M exercises/020_quiz3.zig
M exercises/021_errors.zig
M exercises/022_errors2.zig
M exercises/023_errors3.zig
M exercises/024_errors4.zig
M exercises/025_errors5.zig
M exercises/026_hello2.zig
M exercises/027_defer.zig
M exercises/028_defer2.zig
M exercises/029_errdefer.zig
M exercises/030_switch.zig
M exercises/031_switch2.zig
M exercises/032_unreachable.zig
M exercises/033_iferror.zig
M exercises/034_quiz4.zig
M exercises/035_enums.zig
M exercises/036_enums2.zig
M exercises/037_structs.zig
M exercises/038_structs2.zig
M exercises/039_pointers.zig
M exercises/040_pointers2.zig
M exercises/041_pointers3.zig
M exercises/042_pointers4.zig
M exercises/043_pointers5.zig
M exercises/044_quiz5.zig
M exercises/045_optionals.zig
M exercises/046_optionals2.zig
M exercises/047_methods.zig
M exercises/048_methods2.zig
M exercises/049_quiz6.zig
M exercises/050_no_value.zig
M exercises/051_values.zig
M exercises/052_slices.zig
M exercises/053_slices2.zig
M exercises/054_manypointers.zig
M exercises/055_unions.zig
M exercises/056_unions2.zig
M exercises/057_unions3.zig
M exercises/058_quiz7.zig
M exercises/059_integers.zig
M exercises/060_floats.zig
M exercises/061_coercions.zig
M exercises/062_loop_expressions.zig
M exercises/063_labels.zig
M exercises/064_builtins.zig
M exercises/065_builtins2.zig
M exercises/066_comptime.zig
M exercises/067_comptime2.zig
M exercises/068_comptime3.zig
M exercises/069_comptime4.zig
M exercises/070_comptime5.zig
M exercises/071_comptime6.zig
M exercises/072_comptime7.zig
M exercises/073_comptime8.zig
M exercises/074_comptime9.zig
M exercises/075_quiz8.zig
M exercises/076_sentinels.zig
M exercises/077_sentinels2.zig
M exercises/078_sentinels3.zig
M exercises/079_quoted_identifiers.zig
M exercises/080_anonymous_structs.zig
M exercises/081_anonymous_structs2.zig
M exercises/082_anonymous_structs3.zig
M exercises/083_anonymous_lists.zig
M exercises/084_async.zig
M exercises/085_async2.zig
M exercises/086_async3.zig
M exercises/087_async4.zig
M exercises/088_async5.zig
M exercises/089_async6.zig
M exercises/090_async7.zig
M exercises/091_async8.zig
M exercises/001_hello.zig => exercises/001_hello.zig +1 -1
@@ 16,6 16,6 @@
//
const std = @import("std");

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

M exercises/002_std.zig => exercises/002_std.zig +1 -1
@@ 11,7 11,7 @@
// Please complete the import below:
//

??? = @import("std");
const std = @import("std");

pub fn main() void {
    std.debug.print("Standard Library.\n", .{});

M exercises/003_assignment.zig => exercises/003_assignment.zig +3 -3
@@ 34,12 34,12 @@
const std = @import("std");

pub fn main() void {
    const n: u8 = 50;
    var n: u8 = 50;
    n = n + 5;

    const pi: u8 = 314159;
    const pi: u32 = 314159;

    const negative_eleven: u8 = -11;
    const negative_eleven: i8 = -11;

    // There are no errors in the next line, just explanation:
    // Perhaps you noticed before that the print function takes two

M exercises/004_arrays.zig => exercises/004_arrays.zig +3 -3
@@ 27,7 27,7 @@ pub fn main() void {
    // (Problem 1)
    // This "const" is going to cause a problem later - can you see what it is?
    // How do we fix it?
    const some_primes = [_]u8{ 1, 3, 5, 7, 11, 13, 17, 19 };
    var some_primes = [_]u8{ 1, 3, 5, 7, 11, 13, 17, 19 };

    // Individual values can be set with '[]' notation.
    // Example: This line changes the first prime to 2 (which is correct):


@@ 40,11 40,11 @@ pub fn main() void {
    // (Problem 2)
    // Looks like we need to complete this expression. Use the example
    // above to set "fourth" to the fourth element of the some_primes array:
    const fourth = some_primes[???];
    const fourth = some_primes[3];

    // (Problem 3)
    // Use the len property to get the length of the array:
    const length = some_primes.???;
    const length = some_primes.len;

    std.debug.print("First: {}, Fourth: {}, Length: {}\n", .{
        first, fourth, length,

M exercises/005_arrays2.zig => exercises/005_arrays2.zig +2 -2
@@ 20,12 20,12 @@ pub fn main() void {
    // (Problem 1)
    // Please set this array concatenating the two arrays above.
    // It should result in: 1 3 3 7
    const leet = ???;
    const leet = le ++ et;

    // (Problem 2)
    // Please set this array using repetition.
    // It should result in: 1 0 0 1 1 0 0 1 1 0 0 1
    const bit_pattern = [_]u8{ ??? } ** 3;
    const bit_pattern = [_]u8{ 1, 0, 0, 1 } ** 3;

    // Okay, that's all of the problems. Let's see the results.
    //

M exercises/006_strings.zig => exercises/006_strings.zig +3 -3
@@ 22,18 22,18 @@ pub fn main() void {
    // (Problem 1)
    // Use array square bracket syntax to get the letter 'd' from
    // the string "stardust" above.
    const d: u8 = ziggy[???];
    const d: u8 = ziggy[4];

    // (Problem 2)
    // Use the array repeat '**' operator to make "ha ha ha ".
    const laugh = "ha " ???;
    const laugh = "ha " ** 3;

    // (Problem 3)
    // Use the array concatenation '++' operator to make "Major Tom".
    // (You'll need to add a space as well!)
    const major = "Major";
    const tom = "Tom";
    const major_tom = major ??? tom;
    const major_tom = major ++ [_]u8{' '} ++ tom;

    // That's all the problems. Let's see our results:
    std.debug.print("d={u} {s}{s}\n", .{ d, laugh, major_tom });

M exercises/007_strings2.zig => exercises/007_strings2.zig +3 -3
@@ 15,9 15,9 @@ const std = @import("std");

pub fn main() void {
    const lyrics =
        Ziggy played guitar
        Jamming good with Andrew Kelley
        And the Spiders from Mars
        \\Ziggy played guitar
        \\Jamming good with Andrew Kelley
        \\And the Spiders from Mars
    ;

    std.debug.print("{s}\n", .{lyrics});

M exercises/008_quiz.zig => exercises/008_quiz.zig +4 -4
@@ 19,7 19,7 @@ pub fn main() void {
    // the idiomatic type to use for array indexing.
    //
    // There IS a problem on this line, but 'usize' isn't it.
    const x: usize = 1;
    var x: usize = 1;

    // Note: When you want to declare memory (an array in this
    // case) without putting anything in it, you can set it to


@@ 33,10 33,10 @@ pub fn main() void {
    lang[0] = letters[x];

    x = 3;
    lang[???] = letters[x];
    lang[1] = letters[x];

    x = ???;
    lang[2] = letters[???];
    x = 5;
    lang[2] = letters[x];

    // We want to "Program in Zig!" of course:
    std.debug.print("Program in {s}!\n", .{lang});

M exercises/009_if.zig => exercises/009_if.zig +1 -1
@@ 24,7 24,7 @@ pub fn main() void {
    const foo = 1;

    // Please fix this condition:
    if (foo) {
    if (foo == 1) {
        // We want our program to print this message!
        std.debug.print("Foo is 1!\n", .{});
    } else {

M exercises/010_if2.zig => exercises/010_if2.zig +1 -1
@@ 10,7 10,7 @@ pub fn main() void {

    // Please use an if...else expression to set "price".
    // If discount is true, the price should be $17, otherwise $20:
    var price: u8 = if ???;
    var price: u8 = if (discount) 17 else 20;

    std.debug.print("With the discount, the price is ${}.\n", .{price});
}

M exercises/011_while.zig => exercises/011_while.zig +1 -1
@@ 21,7 21,7 @@ pub fn main() void {
    var n: u32 = 2;

    // Please use a condition that is true UNTIL "n" reaches 1024:
    while (???) {
    while (n < 1024) {
        // Print the current number
        std.debug.print("{} ", .{n});


M exercises/012_while2.zig => exercises/012_while2.zig +1 -1
@@ 25,7 25,7 @@ pub fn main() void {

    // Please set the continue expression so that we get the desired
    // results in the print statement below.
    while (n < 1000) : ??? {
    while (n < 1000) : (n *= 2) {
        // Print the current number
        std.debug.print("{} ", .{n});
    }

M exercises/013_while3.zig => exercises/013_while3.zig +2 -2
@@ 24,8 24,8 @@ pub fn main() void {
    while (n <= 20) : (n += 1) {
        // The '%' symbol is the "modulo" operator and it
        // returns the remainder after division.
        if (n % 3 == 0) ???;
        if (n % 5 == 0) ???;
        if (n % 3 == 0) continue;
        if (n % 5 == 0) continue;
        std.debug.print("{} ", .{n});
    }


M exercises/014_while4.zig => exercises/014_while4.zig +1 -1
@@ 18,7 18,7 @@ pub fn main() void {
    // Oh dear! This while loop will go forever?!
    // Please fix this so the print statement below gives the desired output.
    while (true) : (n += 1) {
        if (???) ???;
        if (n == 4) break;
    }

    // Result: we want n=4

M exercises/015_for.zig => exercises/015_for.zig +1 -1
@@ 15,7 15,7 @@ pub fn main() void {

    std.debug.print("A Dramatic Story: ", .{});

    for (???) |???| {
    for (story) |scene| {
        if (scene == 'h') std.debug.print(":-)  ", .{});
        if (scene == 's') std.debug.print(":-(  ", .{});
        if (scene == 'n') std.debug.print(":-|  ", .{});

M exercises/016_for2.zig => exercises/016_for2.zig +1 -1
@@ 24,7 24,7 @@ pub fn main() void {
    // the value of the place as a power of two for each bit.
    //
    // See if you can figure out the missing piece:
    for (bits) |bit, ???| {
    for (bits) |bit, i| {
        // Note that we convert the usize i to a u32 with
        // @intCast(), a builtin function just like @import().
        // We'll learn about these properly in a later exercise.

M exercises/017_quiz2.zig => exercises/017_quiz2.zig +4 -4
@@ 9,18 9,18 @@
// Let's go from 1 to 16.  This has been started for you, but there's
// some problems. :-(
//
const std = import standard library;
const std = @import("std");

function main() void {
pub fn main() void {
    var i: u8 = 1;
    var stop_at: u8 = 16;

    // What kind of loop is this? A 'for' or a 'while'?
    ??? (i <= stop_at) : (i += 1) {
    while (i <= stop_at) : (i += 1) {
        if (i % 3 == 0) std.debug.print("Fizz", .{});
        if (i % 5 == 0) std.debug.print("Buzz", .{});
        if (!(i % 3 == 0) and !(i % 5 == 0)) {
            std.debug.print("{}", .{???});
            std.debug.print("{}", .{i});
        }
        std.debug.print(", ", .{});
    }

M exercises/018_functions.zig => exercises/018_functions.zig +1 -1
@@ 25,6 25,6 @@ pub fn main() void {
// We're just missing a couple things. One thing we're NOT missing is the
// keyword "pub", which is not needed here. Can you guess why?
//
??? deepThought() ??? {
fn deepThought() u8 {
    return 42; // Number courtesy Douglas Adams
}

M exercises/019_functions2.zig => exercises/019_functions2.zig +1 -1
@@ 22,7 22,7 @@ pub fn main() void {
// You'll need to figure out the parameter name and type that we're
// expecting. The output type has already been specified for you.
//
fn twoToThe(???) u32 {
fn twoToThe(my_number: u32) u32 {
    return std.math.pow(u32, 2, my_number);
    // std.math.pow(type, a, b) takes a numeric type and two
    // numbers of that type (or that can coerce to that type) and

M exercises/020_quiz3.zig => exercises/020_quiz3.zig +6 -6
@@ 8,7 8,7 @@
const std = @import("std");

pub fn main() void {
    const my_numbers = [4]u16{ 5, 6, 7, 8 };
    const my_numbers: [4]u16 = [4]u16{ 5, 6, 7, 8 };

    printPowersOfTwo(my_numbers);
    std.debug.print("\n", .{});


@@ 21,8 21,8 @@ pub fn main() void {
//
// This function prints, but does not return anything.
//
fn printPowersOfTwo(numbers: [4]u16) ??? {
    loop (numbers) |n| {
fn printPowersOfTwo(numbers: [4]u16) void {
    for (numbers) |n| {
        std.debug.print("{} ", .{twoToThe(n)});
    }
}


@@ 31,13 31,13 @@ fn printPowersOfTwo(numbers: [4]u16) ??? {
// exercise. But don't be fooled! This one does the math without the aid
// of the standard library!
//
fn twoToThe(number: u16) ??? {
fn twoToThe(number: u16) u16 {
    var n: u16 = 0;
    var total: u16 = 1;

    loop (n < number) : (n += 1) {
    while (n < number) : (n += 1) {
        total *= 2;
    }

    return ???;
    return total;
}

M exercises/021_errors.zig => exercises/021_errors.zig +2 -2
@@ 9,7 9,7 @@
// "TooSmall". Please add it where needed!
const MyNumberError = error{
    TooBig,
    ???,
    TooSmall,
    TooFour,
};



@@ 26,7 26,7 @@ pub fn main() void {
        if (number_error == MyNumberError.TooBig) {
            std.debug.print(">4. ", .{});
        }
        if (???) {
        if (number_error == MyNumberError.TooSmall) {
            std.debug.print("<4. ", .{});
        }
        if (number_error == MyNumberError.TooFour) {

M exercises/022_errors2.zig => exercises/022_errors2.zig +1 -1
@@ 19,7 19,7 @@ const std = @import("std");
const MyNumberError = error{TooSmall};

pub fn main() void {
    var my_number: ??? = 5;
    var my_number: MyNumberError!u8 = 5;

    // Looks like my_number will need to either store a number OR
    // an error. Can you set the type correctly above?

M exercises/023_errors3.zig => exercises/023_errors3.zig +2 -2
@@ 12,14 12,14 @@ const MyNumberError = error{TooSmall};

pub fn main() void {
    var a: u32 = addTwenty(44) catch 22;
    var b: u32 = addTwenty(4) ??? 22;
    var b: u32 = addTwenty(4) catch 22;

    std.debug.print("a={}, b={}\n", .{ a, b });
}

// Please provide the return type from this function.
// Hint: it'll be an error union.
fn addTwenty(n: u32) ??? {
fn addTwenty(n: u32) MyNumberError!u32 {
    if (n < 5) {
        return MyNumberError.TooSmall;
    } else {

M exercises/024_errors4.zig => exercises/024_errors4.zig +7 -1
@@ 59,7 59,13 @@ fn fixTooSmall(n: u32) MyNumberError!u32 {
    // If we get a TooSmall error, we should return 10.
    // If we get any other error, we should return that error.
    // Otherwise, we return the u32 number.
    return detectProblems(n) ???;
    return detectProblems(n) catch |err| {
        if (err == MyNumberError.TooSmall) {
            return 10;
        }

        return err;
    };
}

fn detectProblems(n: u32) MyNumberError!u32 {

M exercises/025_errors5.zig => exercises/025_errors5.zig +1 -1
@@ 26,7 26,7 @@ fn addFive(n: u32) MyNumberError!u32 {
    // This function needs to return any error which might come back from detect().
    // Please use a "try" statement rather than a "catch".
    //
    var x = detect(n);
    var x = try detect(n);

    return x + 5;
}

M exercises/026_hello2.zig => exercises/026_hello2.zig +1 -1
@@ 19,5 19,5 @@ pub fn main() !void {
    // to be able to pass it up as a return value of main().
    //
    // We just learned of a single statement which can accomplish this.
    stdout.print("Hello world!\n", .{});
    try stdout.print("Hello world!\n", .{});
}

M exercises/027_defer.zig => exercises/027_defer.zig +1 -1
@@ 20,6 20,6 @@ const std = @import("std");
pub fn main() void {
    // Without changing anything else, please add a 'defer' statement
    // to this code so that our program prints "One Two\n":
    std.debug.print("Two\n", .{});
    defer std.debug.print("Two\n", .{});
    std.debug.print("One ", .{});
}

M exercises/028_defer2.zig => exercises/028_defer2.zig +1 -1
@@ 18,7 18,7 @@ pub fn main() void {
fn printAnimal(animal: u8) void {
    std.debug.print("(", .{});

    std.debug.print(") ", .{}); // <---- how?!
    defer std.debug.print(") ", .{}); // <---- how?!

    if (animal == 'g') {
        std.debug.print("Goat", .{});

M exercises/029_errdefer.zig => exercises/029_errdefer.zig +1 -1
@@ 32,7 32,7 @@ fn makeNumber() MyErr!u32 {

    // Please make the "failed" message print ONLY if the makeNumber()
    // function exits with an error:
    std.debug.print("failed!\n", .{});
    errdefer std.debug.print("failed!\n", .{});

    var num = try getNumber(); // <-- This could fail!


M exercises/030_switch.zig => exercises/030_switch.zig +3 -0
@@ 46,6 46,9 @@ pub fn main() void {
            // match for every possible value).  Please add an "else"
            // to this switch to print a question mark "?" when c is
            // not one of the existing matches.
            else => {
                std.debug.print("?", .{});
            },
        }
    }


M exercises/031_switch2.zig => exercises/031_switch2.zig +1 -0
@@ 29,6 29,7 @@ pub fn main() void {
            // ...
            25 => 'Y',
            26 => 'Z',
            else => '!',
            // As in the last exercise, please add the 'else' clause
            // and this time, have it return an exclamation mark '!'.
        };

M exercises/032_unreachable.zig => exercises/032_unreachable.zig +1 -0
@@ 35,6 35,7 @@ pub fn main() void {
            3 => {
                current_value *= current_value;
            },
            else => unreachable,
        }

        std.debug.print("{} ", .{current_value});

M exercises/033_iferror.zig => exercises/033_iferror.zig +1 -0
@@ 39,6 39,7 @@ pub fn main() void {
            std.debug.print("={}. ", .{value});
        } else |err| switch (err) {
            MyNumberError.TooBig => std.debug.print(">4. ", .{}),
            MyNumberError.TooSmall => std.debug.print("<4. ", .{}),
            // Please add a match for TooSmall here and have it print: "<4. "
        }
    }

M exercises/034_quiz4.zig => exercises/034_quiz4.zig +5 -2
@@ 12,9 12,12 @@ const NumError = error{IllegalNumber};
pub fn main() void {
    const stdout = std.io.getStdOut().writer();

    const my_num: u32 = getNumber();
    var my_num: u32 = getNumber() catch 42;

    try stdout.print("my_num={}\n", .{my_num});
    stdout.print("my_num={}\n", .{my_num}) catch {
        std.debug.print("a={}\n", .{my_num});
        return;
    };
}

// This function is obviously weird and non-functional. But you will not be changing it for this quiz.

M exercises/035_enums.zig => exercises/035_enums.zig +1 -1
@@ 20,7 20,7 @@
const std = @import("std");

// Please complete the enum!
const Ops = enum { ??? };
const Ops = enum { inc, pow, dec };

pub fn main() void {
    const operations = [_]Ops{

M exercises/036_enums2.zig => exercises/036_enums2.zig +3 -3
@@ 31,7 31,7 @@ const std = @import("std");
const Color = enum(u32) {
    red = 0xff0000,
    green = 0x00ff00,
    blue = ???,
    blue = 0x0000ff,
};

pub fn main() void {


@@ 53,12 53,12 @@ pub fn main() void {
        \\<p>
        \\  <span style="color: #{x:0>6}">Red</span>
        \\  <span style="color: #{x:0>6}">Green</span>
        \\  <span style="color: #{}">Blue</span>
        \\  <span style="color: #{x:0>6}">Blue</span>
        \\</p>
        \\
    , .{
        @enumToInt(Color.red),
        @enumToInt(Color.green),
        @enumToInt(???), // Oops! We're missing something!
        @enumToInt(Color.blue), // Oops! We're missing something!
    });
}

M exercises/037_structs.zig => exercises/037_structs.zig +2 -0
@@ 36,6 36,7 @@ const Character = struct {
    class: Class,
    gold: u32,
    experience: u32,
    health: u8,
};

pub fn main() void {


@@ 44,6 45,7 @@ pub fn main() void {
        .class = Class.wizard,
        .gold = 20,
        .experience = 10,
        .health = 100,
    };

    // Glorp gains some gold.

M exercises/038_structs2.zig => exercises/038_structs2.zig +7 -0
@@ 33,6 33,13 @@ pub fn main() void {
        .experience = 10,
    };

    chars[1] = Character{
        .class = Class.wizard,
        .gold = 10,
        .health = 100,
        .experience = 20,
    };

    // Please add "Zump the Loud" with the following properties:
    //
    //     class      bard

M exercises/039_pointers.zig => exercises/039_pointers.zig +1 -1
@@ 30,7 30,7 @@ pub fn main() void {

    // Please make num2 equal 5 using num1_pointer!
    // (See the "cheatsheet" above for ideas.)
    num2 = ???;
    num2 = num1_pointer.*;

    std.debug.print("num1: {}, num2: {}\n", .{ num1, num2 });
}

M exercises/040_pointers2.zig => exercises/040_pointers2.zig +1 -1
@@ 20,7 20,7 @@
const std = @import("std");

pub fn main() void {
    const a: u8 = 12;
    var a: u8 = 12;
    const b: *u8 = &a; // fix this!

    std.debug.print("a: {}, b: {}\n", .{ a, b.* });

M exercises/041_pointers3.zig => exercises/041_pointers3.zig +1 -1
@@ 31,7 31,7 @@ pub fn main() void {

    // Please define pointer "p" so that it can point to EITHER foo or
    // bar AND change the value it points to!
    ??? p: ??? = undefined;
    var p: *u8 = undefined;

    p = &foo;
    p.* += 1;

M exercises/042_pointers4.zig => exercises/042_pointers4.zig +1 -1
@@ 28,5 28,5 @@ pub fn main() void {
// This function should take a reference to a u8 value and set it
// to 5.
fn makeFive(x: *u8) void {
    ??? = 5; // fix me!
    x.* = 5; // fix me!
}

M exercises/043_pointers5.zig => exercises/043_pointers5.zig +1 -1
@@ 57,7 57,7 @@ pub fn main() void {

    // FIX ME!
    // Please pass our Character "glorp" to printCharacter():
    printCharacter(???);
    printCharacter(&glorp);
}

// Note how this function's "c" parameter is a pointer to a Character struct.

M exercises/044_quiz5.zig => exercises/044_quiz5.zig +2 -0
@@ 19,12 19,14 @@ const Elephant = struct {
pub fn main() void {
    var elephantA = Elephant{ .letter = 'A' };
    // (Please add Elephant B here!)
    var elephantB = Elephant{ .letter = 'B' };
    var elephantC = Elephant{ .letter = 'C' };

    // Link the elephants so that each tail "points" to the next elephant.
    // They make a circle: A->B->C->A...
    elephantA.tail = &elephantB;
    // (Please link Elephant B's tail to Elephant C here!)
    elephantB.tail = &elephantC;
    elephantC.tail = &elephantA;

    visitElephants(&elephantA);

M exercises/045_optionals.zig => exercises/045_optionals.zig +1 -1
@@ 29,7 29,7 @@ pub fn main() void {

    // Please threaten the result so that answer is either the
    // integer value from deepThought() OR the number 42:
    var answer: u8 = result;
    var answer: u8 = result orelse 42;

    std.debug.print("The Ultimate Answer: {}.\n", .{answer});
}

M exercises/046_optionals2.zig => exercises/046_optionals2.zig +2 -2
@@ 21,7 21,7 @@ const std = @import("std");

const Elephant = struct {
    letter: u8,
    tail: *Elephant = null, // Hmm... tail needs something...
    tail: ?*Elephant = null, // Hmm... tail needs something...
    visited: bool = false,
};



@@ 51,7 51,7 @@ fn visitElephants(first_elephant: *Elephant) void {
        // We should stop once we encounter a tail that
        // does NOT point to another element. What can
        // we put here to make that happen?
        if (e.tail == null) ???;
        if (e.tail == null) break;

        e = e.tail.?;
    }

M exercises/047_methods.zig => exercises/047_methods.zig +1 -1
@@ 84,7 84,7 @@ pub fn main() void {
        for (aliens) |*alien| {

            // *** Zap the Alien Here! ***
            ???.zap(heat_ray_strength);
            alien.zap(heat_ray_strength);

            // If the alien's health is still above 0, it's still alive.
            if (alien.health > 0) aliens_alive += 1;

M exercises/048_methods2.zig => exercises/048_methods2.zig +1 -1
@@ 54,7 54,7 @@ fn visitElephants(first_elephant: *Elephant) void {

        // This gets the next elephant or stops.
        if (e.hasTail()) {
            e = e.???; // Which method do we want here?
            e = e.getTail(); // Which method do we want here?
        } else {
            break;
        }

M exercises/049_quiz6.zig => exercises/049_quiz6.zig +6 -1
@@ 27,8 27,13 @@ const Elephant = struct {
    // Your Elephant trunk methods go here!
    // ---------------------------------------------------

    ???
    pub fn getTrunk(self: *Elephant) *Elephant {
        return self.trunk.?; // Remember, this means "orelse unreachable"
    }

    pub fn hasTrunk(self: *Elephant) bool {
        return (self.trunk != null);
    }
    // ---------------------------------------------------

    pub fn visit(self: *Elephant) void {

M exercises/050_no_value.zig => exercises/050_no_value.zig +4 -4
@@ 65,10 65,10 @@ const std = @import("std");
const Err = error{Cthulhu};

pub fn main() void {
    var first_line1: *const [16]u8 = ???;
    var first_line1: *const [16]u8 = undefined;
    first_line1 = "That is not dead";

    var first_line2: Err!*const [21]u8 = ???;
    var first_line2: Err!*const [21]u8 = Err.Cthulhu;
    first_line2 = "which can eternal lie";

    std.debug.print("{s} {s} / ", .{ first_line1, first_line2 });


@@ 76,8 76,8 @@ pub fn main() void {
    printSecondLine();
}

fn printSecondLine() ??? {
    var second_line2: ?*const [18]u8 = ???;
fn printSecondLine() void {
    var second_line2: ?*const [18]u8 = undefined;
    second_line2 = "even death may die";

    std.debug.print("And with strange aeons {s}.\n", .{second_line2.?});

M exercises/051_values.zig => exercises/051_values.zig +3 -3
@@ 87,7 87,7 @@ pub fn main() void {
    // Let's assign the std.debug.print function to a const named
    // "print" so that we can use this new name later!

    const print = ???;
    const print = std.debug.print;

    // Now let's look at assigning and pointing to values in Zig.
    //


@@ 152,13 152,13 @@ pub fn main() void {
    print("XP before:{}, ", .{glorp.experience});

    // Fix 1 of 2 goes here:
    levelUp(glorp, reward_xp);
    levelUp(glorp_access3, reward_xp);

    print("after:{}.\n", .{glorp.experience});
}

// Fix 2 of 2 goes here:
fn levelUp(character_access: Character, xp: u32) void {
fn levelUp(character_access: *Character, xp: u32) void {
    character_access.experience += xp;
}


M exercises/052_slices.zig => exercises/052_slices.zig +3 -3
@@ 32,8 32,8 @@ pub fn main() void {
    var cards = [8]u8{ 'A', '4', 'K', '8', '5', '2', 'Q', 'J' };

    // Please put the first 4 cards in hand1 and the rest in hand2.
    const hand1: []u8 = cards[???];
    const hand2: []u8 = cards[???];
    const hand1: []u8 = cards[0..4];
    const hand2: []u8 = cards[4..];

    std.debug.print("Hand1: ", .{});
    printHand(hand1);


@@ 43,7 43,7 @@ pub fn main() void {
}

// Please lend this function a hand. A u8 slice hand, that is.
fn printHand(hand: ???) void {
fn printHand(hand: []u8) void {
    for (hand) |h| {
        std.debug.print("{u} ", .{h});
    }

M exercises/053_slices2.zig => exercises/053_slices2.zig +7 -7
@@ 17,19 17,19 @@ const std = @import("std");
pub fn main() void {
    const scrambled = "great base for all your justice are belong to us";

    const base1: []u8 = scrambled[15..23];
    const base2: []u8 = scrambled[6..10];
    const base3: []u8 = scrambled[32..];
    const base1: []const u8 = scrambled[15..23];
    const base2: []const u8 = scrambled[6..10];
    const base3: []const u8 = scrambled[32..];
    printPhrase(base1, base2, base3);

    const justice1: []u8 = scrambled[11..14];
    const justice2: []u8 = scrambled[0..5];
    const justice3: []u8 = scrambled[24..31];
    const justice1: []const u8 = scrambled[11..14];
    const justice2: []const u8 = scrambled[0..5];
    const justice3: []const u8 = scrambled[24..31];
    printPhrase(justice1, justice2, justice3);

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

fn printPhrase(part1: []u8, part2: []u8, part3: []u8) void {
fn printPhrase(part1: []const u8, part2: []const u8, part3: []const u8) void {
    std.debug.print("'{s} {s} {s}.' ", .{ part1, part2, part3 });
}

M exercises/054_manypointers.zig => exercises/054_manypointers.zig +1 -1
@@ 32,7 32,7 @@ pub fn main() void {
    // we can CONVERT IT TO A SLICE. (Hint: we do know the length!)
    //
    // Please fix this line so the print statement below can print it:
    const zen12_string: []const u8 = zen_manyptr;
    const zen12_string: []const u8 = zen_manyptr[0..21];

    // Here's the moment of truth!
    std.debug.print("{s}\n", .{zen12_string});

M exercises/055_unions.zig => exercises/055_unions.zig +2 -2
@@ 59,8 59,8 @@ pub fn main() void {
    std.debug.print("Insect report! ", .{});

    // Oops! We've made a mistake here.
    printInsect(ant, AntOrBee.c);
    printInsect(bee, AntOrBee.c);
    printInsect(ant, AntOrBee.a);
    printInsect(bee, AntOrBee.b);

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

M exercises/056_unions2.zig => exercises/056_unions2.zig +3 -3
@@ 44,14 44,14 @@ pub fn main() void {
    std.debug.print("Insect report! ", .{});

    // Could it really be as simple as just passing the union?
    printInsect(???);
    printInsect(???);
    printInsect(ant);
    printInsect(bee);

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

fn printInsect(insect: Insect) void {
    switch (???) {
    switch (insect) {
        .still_alive => |a| std.debug.print("Ant alive is: {}. ", .{a}),
        .flowers_visited => |f| std.debug.print("Bee visited {} flowers. ", .{f}),
    }

M exercises/057_unions3.zig => exercises/057_unions3.zig +1 -1
@@ 15,7 15,7 @@
//
const std = @import("std");

const Insect = union(InsectStat) {
const Insect = union(enum) {
    flowers_visited: u16,
    still_alive: bool,
};

M exercises/058_quiz7.zig => exercises/058_quiz7.zig +18 -18
@@ 107,7 107,7 @@ const Path = struct {
const a_paths = [_]Path{
    Path{
        .from = &a, // from: Archer's Point
        .to = &b,   //   to: Bridge
        .to = &b, //   to: Bridge
        .dist = 2,
    },
};


@@ 115,12 115,12 @@ const a_paths = [_]Path{
const b_paths = [_]Path{
    Path{
        .from = &b, // from: Bridge
        .to = &a,   //   to: Archer's Point
        .to = &a, //   to: Archer's Point
        .dist = 2,
    },
    Path{
        .from = &b, // from: Bridge
        .to = &d,   //   to: Dogwood Grove
        .to = &d, //   to: Dogwood Grove
        .dist = 1,
    },
};


@@ 128,12 128,12 @@ const b_paths = [_]Path{
const c_paths = [_]Path{
    Path{
        .from = &c, // from: Cottage
        .to = &d,   //   to: Dogwood Grove
        .to = &d, //   to: Dogwood Grove
        .dist = 3,
    },
    Path{
        .from = &c, // from: Cottage
        .to = &e,   //   to: East Pond
        .to = &e, //   to: East Pond
        .dist = 2,
    },
};


@@ 141,17 141,17 @@ const c_paths = [_]Path{
const d_paths = [_]Path{
    Path{
        .from = &d, // from: Dogwood Grove
        .to = &b,   //   to: Bridge
        .to = &b, //   to: Bridge
        .dist = 1,
    },
    Path{
        .from = &d, // from: Dogwood Grove
        .to = &c,   //   to: Cottage
        .to = &c, //   to: Cottage
        .dist = 3,
    },
    Path{
        .from = &d, // from: Dogwood Grove
        .to = &f,   //   to: Fox Pond
        .to = &f, //   to: Fox Pond
        .dist = 7,
    },
};


@@ 159,20 159,20 @@ const d_paths = [_]Path{
const e_paths = [_]Path{
    Path{
        .from = &e, // from: East Pond
        .to = &c,   //   to: Cottage
        .to = &c, //   to: Cottage
        .dist = 2,
    },
    Path{
        .from = &e, // from: East Pond
        .to = &f,   //   to: Fox Pond
        .dist = 1,  // (one-way down a short waterfall!)
        .to = &f, //   to: Fox Pond
        .dist = 1, // (one-way down a short waterfall!)
    },
};

const f_paths = [_]Path{
    Path{
        .from = &f, // from: Fox Pond
        .to = &d,   //   to: Dogwood Grove
        .to = &d, //   to: Dogwood Grove
        .dist = 7,
    },
};


@@ 192,8 192,8 @@ const TripItem = union(enum) {
            // Oops! The hermit forgot how to capture the union values
            // in a switch statement. Please capture both values as
            // 'p' so the print statements work!
            .place => print("{s}", .{p.name}),
            .path => print("--{}->", .{p.dist}),
            .place => |p| print("{s}", .{p.name}),
            .path => |p| print("--{}->", .{p.dist}),
        }
    }
};


@@ 255,7 255,7 @@ const HermitsNotebook = struct {
            // dereference and optional value "unwrapping" look
            // together. Remember that you return the address with the
            // "&" operator.
            if (place == entry.*.?.place) return entry;
            if (place == entry.*.?.place) return &entry.*.?;
            // Try to make your answer this long:__________;
        }
        return null;


@@ 309,7 309,7 @@ const HermitsNotebook = struct {
    //
    // Looks like the hermit forgot something in the return value of
    // this function. What could that be?
    fn getTripTo(self: *HermitsNotebook, trip: []?TripItem, dest: *Place) void {
    fn getTripTo(self: *HermitsNotebook, trip: []?TripItem, dest: *Place) !void {
        // We start at the destination entry.
        const destination_entry = self.getEntry(dest);



@@ 355,8 355,8 @@ pub fn main() void {
    // Here's where the hermit decides where he would like to go. Once
    // you get the program working, try some different Places on the
    // map!
    const start = &a;        // Archer's Point
    const destination = &f;  // Fox Pond
    const start = &a; // Archer's Point
    const destination = &f; // Fox Pond

    // Store each Path array as a slice in each Place. As mentioned
    // above, we needed to delay making these references to avoid

M exercises/059_integers.zig => exercises/059_integers.zig +4 -4
@@ 18,10 18,10 @@
const print = @import("std").debug.print;

pub fn main() void {
    var zig = [_]u8 {
        0o131,     // octal
        0b1101000, // binary
        0x66,      // hex
    var zig = [_]u8{
        0o132, // octal
        0b1101001, // binary
        0x67, // hex
    };

    print("{s} is cool.\n", .{zig});

M exercises/060_floats.zig => exercises/060_floats.zig +1 -1
@@ 40,7 40,7 @@ pub fn main() void {
    //
    // We'll convert this weight from tons to kilograms at a
    // conversion of 907.18kg to the ton.
    var shuttle_weight: f16 = 907.18 * 2200;
    var shuttle_weight: f32 = 907.18 * 2200.0;

    // By default, float values are formatted in scientific
    // notation. Try experimenting with '{d}' and '{d:.3}' to see

M exercises/061_coercions.zig => exercises/061_coercions.zig +1 -1
@@ 67,7 67,7 @@ const print = @import("std").debug.print;
pub fn main() void {
    var letter: u8 = 'A';

    const my_letter:   ???   = &letter;
    const my_letter: ?*[1]u8 = &letter;
    //               ^^^^^^^
    //           Your type here.
    // Must coerce from &letter (which is a *u8).

M exercises/062_loop_expressions.zig => exercises/062_loop_expressions.zig +1 -1
@@ 47,7 47,7 @@ pub fn main() void {
    // return it from the for loop.
    const current_lang: ?[]const u8 = for (langs) |lang| {
        if (lang.len == 3) break lang;
    };
    } else null;

    if (current_lang) |cl| {
        print("Current language: {s}\n", .{cl});

M exercises/063_labels.zig => exercises/063_labels.zig +1 -1
@@ 129,7 129,7 @@ pub fn main() void {
        //
        // Please return this Food from the loop.
        break;
    };
    } else menu[menu.len - 1];
    // ^ Oops! We forgot to return Mac & Cheese as the default
    // Food when the requested ingredients aren't found.


M exercises/064_builtins.zig => exercises/064_builtins.zig +1 -1
@@ 69,6 69,6 @@ pub fn main() void {
    // Now it's your turn. See if you can fix this attempt to use
    // this builtin to reverse the bits of a u8 integer.
    const input: u8 = 0b11110000;
    const tupni: u8 = @bitReverse(input);
    const tupni: u8 = @bitReverse(u8, input);
    print("{b:0>8} backwards is {b:0>8}.\n", .{ input, tupni });
}

M exercises/065_builtins2.zig => exercises/065_builtins2.zig +8 -9
@@ 40,7 40,7 @@
// (Notice how the two functions which return types start with
// uppercase letters? This is a standard naming practice in Zig.)
//
const print = import(std).debug.print; // Oops!
const print = @import("std").debug.print; // Oops!

const Narcissus = struct {
    me: *Narcissus = undefined,


@@ 57,18 57,17 @@ pub fn main() void {

    // Oops! We cannot leave the 'me' and 'myself' fields
    // undefined. Please set them here:
    ??? = &narcissus;
    ??? = &narcissus;
    const me = &narcissus;
    const myself = &narcissus;

    // This determines a "peer type" from three separate
    // references (they just happen to all be the same object).
    const T1 = @TypeOf(narcissus, narcissus.me.*, narcissus.myself.*);

    const T1 = @TypeOf(narcissus, me.*, myself.*);
    // Oh dear, we seem to have done something wrong when calling
    // this function. It is namespaced to the struct, but doesn't
    // use the method syntax (there's no self parameter). Please
    // fix this call:
    const T2 = narcissus.fetchTheMostBeautifulType();
    const T2 = Narcissus.fetchTheMostBeautifulType();

    print("A {} loves all {}es. ", .{ T1, T2 });



@@ 103,15 102,15 @@ pub fn main() void {
    // Please complete these 'if' statements so that the field
    // name will not be printed if the field is of type 'void'
    // (which is a zero-bit type that takes up no space at all!):
    if (fields[0].??? != void) {
    if (fields[0].field_type != void) {
        print(" {s}", .{@typeInfo(Narcissus).Struct.fields[0].name});
    }

    if (fields[1].??? != void) {
    if (fields[1].field_type != void) {
        print(" {s}", .{@typeInfo(Narcissus).Struct.fields[1].name});
    }

    if (fields[2].??? != void) {
    if (fields[2].field_type != void) {
        print(" {s}", .{@typeInfo(Narcissus).Struct.fields[2].name});
    }


M exercises/066_comptime.zig => exercises/066_comptime.zig +2 -2
@@ 61,8 61,8 @@ pub fn main() void {
    // values. Therefore, it follows that we just specify numeric
    // types with specific sizes. The comptime numbers will be
    // coerced (if they'll fit!) into your chosen runtime types.
    var var_int = 12345;
    var var_float = 987.654;
    var var_int: u32 = 12345;
    var var_float: f32 = 987.654;

    // We can change what is stored at the areas set aside for
    // "var_int" and "var_float" in the running compiled program.

M exercises/067_comptime2.zig => exercises/067_comptime2.zig +2 -2
@@ 35,13 35,14 @@ pub fn main() void {
    // In this contrived example, we've decided to allocate some
    // arrays using a variable count! But something's missing...
    //
    var count = 0;
    comptime var count = 0;

    count += 1;
    var a1: [count]u8 = .{'A'} ** count;

    count += 1;
    var a2: [count]u8 = .{'B'} ** count;
    //@compileLog("Count at compile time: ", count);

    count += 1;
    var a3: [count]u8 = .{'C'} ** count;


@@ 60,5 61,4 @@ pub fn main() void {
    //
    // Try uncommenting this line and playing around with it
    // (copy it, move it) to see what it does:
    //@compileLog("Count at compile time: ", count);
}

M exercises/068_comptime3.zig => exercises/068_comptime3.zig +2 -2
@@ 43,7 43,7 @@ const Schooner = struct {
        //
        // Please change this so that it sets a 0 scale to 1
        // instead.
        if (my_scale == 0) @compileError("Scale 1:0 is not valid!");
        if (my_scale == 0) my_scale = 1;

        self.scale = my_scale;
        self.hull_length /= my_scale;


@@ 69,7 69,7 @@ pub fn main() void {
    // Hey, we can't just pass this runtime variable as an
    // argument to the scaleMe() method. What would let us do
    // that?
    var scale: u32 = undefined;
    comptime var scale: u32 = undefined;

    scale = 32; // 1:32 scale


M exercises/069_comptime4.zig => exercises/069_comptime4.zig +3 -3
@@ 16,7 16,7 @@ const print = @import("std").debug.print;
pub fn main() void {
    // Here we declare arrays of three different types and sizes
    // at compile time from a function call. Neat!
    const s1 = makeSequence(u8, 3);  // creates a [3]u8
    const s1 = makeSequence(u8, 3); // creates a [3]u8
    const s2 = makeSequence(u32, 5); // creates a [5]u32
    const s3 = makeSequence(i64, 7); // creates a [7]i64



@@ 42,8 42,8 @@ pub fn main() void {
//     2) Sets the size of the array of type T (which is the
//        sequence we're creating and returning).
//
fn makeSequence(comptime T: type, ??? size: usize) [???]T {
    var sequence: [???]T = undefined;
fn makeSequence(comptime T: type, comptime size: usize) [size]T {
    var sequence: [size]T = undefined;
    var i: usize = 0;

    while (i < size) : (i += 1) {

M exercises/070_comptime5.zig => exercises/070_comptime5.zig +2 -2
@@ 123,8 123,8 @@ fn isADuck(possible_duck: anytype) bool {
    // Please make sure MyType has both waddle() and quack()
    // methods:
    const MyType = @TypeOf(possible_duck);
    const walks_like_duck = ???;
    const quacks_like_duck = ???;
    const walks_like_duck = @hasDecl(MyType, "waddle");
    const quacks_like_duck = @hasDecl(MyType, "quack");

    const is_duck = walks_like_duck and quacks_like_duck;


M exercises/071_comptime6.zig => exercises/071_comptime6.zig +1 -1
@@ 40,7 40,7 @@ pub fn main() void {

    const fields = @typeInfo(Narcissus).Struct.fields;

    ??? {
    inline for (fields) |field| {
        if (field.field_type != void) {
            print(" {s}", .{field.name});
        }

M exercises/072_comptime7.zig => exercises/072_comptime7.zig +1 -1
@@ 35,7 35,7 @@ pub fn main() void {
    // at compile time.
    //
    // Please fix this to loop once per "instruction":
    ??? (i < instructions.len) : (???) {
    inline while (i < instructions.len) : (i += 3) {

        // This gets the digit from the "instruction". Can you
        // figure out why we subtract '0' from it?

M exercises/073_comptime8.zig => exercises/073_comptime8.zig +5 -5
@@ 32,12 32,12 @@ const llamas = [llama_count]u32{ 5, 10, 15, 20, 25 };
pub fn main() void {
    // We meant to fetch the last llama. Please fix this simple
    // mistake so the assertion no longer fails.
    const my_llama = getLlama(5);
    const my_llama = comptime getLlama(5);

    print("My llama value is {}.\n", .{my_llama});
}

fn getLlama(i: usize) u32 {
fn getLlama(comptime i: usize) u32 {
    // We've put a guard assert() at the top of this function to
    // prevent mistakes. The 'comptime' keyword here means that
    // the mistake will be caught when we compile!


@@ 50,15 50,15 @@ fn getLlama(i: usize) u32 {
    // because the 'i' parameter needs to be guaranteed to be
    // known at compile time. What can you do with the 'i'
    // parameter above to make this so?
    comptime assert(i < llama_count);
    assert(i < llama_count);

    return llamas[i];
    return llamas[i - 1];
}

// Fun fact: this assert() function is identical to
// std.debug.assert() from the Zig Standard Library.
fn assert(ok: bool) void {
    if (!ok) unreachable;
    if (ok) unreachable;
}
//
// Bonus fun fact: I accidentally replaced all instances of 'foo'

M exercises/074_comptime9.zig => exercises/074_comptime9.zig +1 -1
@@ 39,7 39,7 @@ const llamas = makeLlamas(llama_count);

// And here's the function. Note that the return value type
// depends on one of the input arguments!
fn makeLlamas(count: usize) [count]u8 {
fn makeLlamas(comptime count: usize) [count]u8 {
    var temp: [count]u8 = undefined;
    var i = 0;


M exercises/075_quiz8.zig => exercises/075_quiz8.zig +4 -4
@@ 48,8 48,8 @@ const Path = struct {
// instead.
//
// Please fill in the body of this function!
fn makePath(from: *Place, to: *Place, dist: u8) Path {

fn makePath(comptime from: *Place, comptime to: *Place, comptime dist: u8) Path {
    return Path{ .from = from, .to = to, .dist = dist };
}

// Using our new function, these path definitions take up considerably less


@@ 151,8 151,8 @@ const HermitsNotebook = struct {
};

pub fn main() void {
    const start = &a;        // Archer's Point
    const destination = &f;  // Fox Pond
    const start = &a; // Archer's Point
    const destination = &f; // Fox Pond

    // TODO: can we neaten this up????
    a.paths = a_paths[0..];

M exercises/076_sentinels.zig => exercises/076_sentinels.zig +2 -2
@@ 81,7 81,7 @@ fn printSequence(my_seq: anytype) void {
            print("Array:", .{});

            // Loop through the items in my_seq.
            for (???) |s| {
            for (my_seq) |s| {
                print("{}", .{s});
            }
        },


@@ 93,7 93,7 @@ fn printSequence(my_seq: anytype) void {
            // Loop through the items in my_seq until we hit the
            // sentinel value.
            var i: usize = 0;
            while (??? != my_sentinel) {
            while (my_seq[i] != my_sentinel) {
                print("{}", .{my_seq[i]});
                i += 1;
            }

M exercises/077_sentinels2.zig => exercises/077_sentinels2.zig +1 -1
@@ 60,7 60,7 @@ pub fn main() void {
    // length... You've actually solved this problem before!
    //
    // Here's a big hint: do you remember how to take a slice?
    const printable = ???;
    const printable = foo.data[0..foo.length];

    print("{s}\n", .{printable});
}

M exercises/078_sentinels3.zig => exercises/078_sentinels3.zig +1 -1
@@ 21,7 21,7 @@ pub fn main() void {
    const data: [*]const u8 = "Weird Data!";

    // Please cast 'data' to 'printable':
    const printable: [*:0]const u8 = ???;
    const printable: [*:0]const u8 = @ptrCast([*:0]const u8, data);

    print("{s}\n", .{printable});
}

M exercises/079_quoted_identifiers.zig => exercises/079_quoted_identifiers.zig +5 -5
@@ 20,11 20,11 @@
const print = @import("std").debug.print;

pub fn main() void {
    const 55_cows: i32 = 55;
    const isn't true: bool = false;
    
    const @"55_cows": i32 = 55;
    const @"isn't true": bool = false;

    print("Sweet freedom: {}, {}.\n", .{
        55_cows,
        isn't true,
        @"55_cows",
        @"isn't true",
    });
}

M exercises/080_anonymous_structs.zig => exercises/080_anonymous_structs.zig +2 -2
@@ 48,13 48,13 @@ pub fn main() void {
    // * circle1 should hold i32 integers
    // * circle2 should hold f32 floats
    //
    var circle1 = ??? {
    var circle1 = Circle(i32){
        .center_x = 25,
        .center_y = 70,
        .radius = 15,
    };

    var circle2 = ??? {
    var circle2 = Circle(f32){
        .center_x = 25.234,
        .center_y = 70.999,
        .radius = 15.714,

M exercises/081_anonymous_structs2.zig => exercises/081_anonymous_structs2.zig +1 -1
@@ 38,7 38,7 @@ pub fn main() void {

// Please complete this function which prints an anonymous struct
// representing a circle.
fn printCircle(???) void {
fn printCircle(circle: anytype) void {
    print("x:{} y:{} radius:{}\n", .{
        circle.center_x,
        circle.center_y,

M exercises/082_anonymous_structs3.zig => exercises/082_anonymous_structs3.zig +5 -5
@@ 82,14 82,14 @@ fn printTuple(tuple: anytype) void {
    //         @typeInfo(Circle).Struct.fields
    //
    // This will be an array of StructFields.
    const fields = ???;
    const fields = @typeInfo(@TypeOf(tuple)).Struct.fields;

    // 2. Loop through each field. This must be done at compile
    // time.
    //
    //     Hint: remember 'inline' loops?
    //
    for (fields) |field| {
    inline for (fields) |field| {
        // 3. Print the field's name, type, and value.
        //
        //     Each 'field' in this loop is one of these:


@@ 117,9 117,9 @@ fn printTuple(tuple: anytype) void {
        //
        // The first field should print as: "0"(bool):true
        print("\"{s}\"({s}):{any} ", .{
            field.???,
            field.???,
            ???,
            field.name,
            field.field_type,
            field.default_value,
        });
    }
}

M exercises/083_anonymous_lists.zig => exercises/083_anonymous_lists.zig +1 -1
@@ 20,6 20,6 @@ pub fn main() void {
    //
    //     = .{'h', 'e', 'l', 'l', 'o'};
    //
    const hello = .{'h', 'e', 'l', 'l', 'o'};
    const hello: [5]u8 = .{ 'h', 'e', 'l', 'l', 'o' };
    print("I say {s}!\n", .{hello});
}

M exercises/084_async.zig => exercises/084_async.zig +1 -1
@@ 48,7 48,7 @@ const print = @import("std").debug.print;
pub fn main() void {
    // Additional Hint: you can assign things to '_' when you
    // don't intend to do anything with them.
    foo();
    _ = async foo();
}

fn foo() void {

M exercises/085_async2.zig => exercises/085_async2.zig +1 -0
@@ 19,6 19,7 @@ const print = @import("std").debug.print;

pub fn main() void {
    var foo_frame = async foo();
    resume foo_frame;
}

fn foo() void {

M exercises/086_async3.zig => exercises/086_async3.zig +4 -1
@@ 13,7 13,10 @@ pub fn main() void {
    const n = 5;
    var foo_frame = async foo(n);

    ???
    resume foo_frame;
    resume foo_frame;
    resume foo_frame;
    resume foo_frame;

    print("\n", .{});
}

M exercises/087_async4.zig => exercises/087_async4.zig +3 -3
@@ 16,7 16,7 @@ pub fn main() void {

    while (global_counter <= 5) {
        print("{} ", .{global_counter});
        ???
        resume foo_frame;
    }

    print("\n", .{});


@@ 24,7 24,7 @@ pub fn main() void {

fn foo() void {
    while (true) {
        ???
        ???
        global_counter += 1;
        suspend {}
    }
}

M exercises/088_async5.zig => exercises/088_async5.zig +1 -1
@@ 36,7 36,7 @@ const print = @import("std").debug.print;
pub fn main() void {
    var myframe = async getPageTitle("http://example.com");

    var value = ???
    var value = await myframe;

    print("{s}\n", .{value});
}

M exercises/089_async6.zig => exercises/089_async6.zig +2 -2
@@ 41,8 41,8 @@ pub fn main() void {
    var com_frame = async getPageTitle("http://example.com");
    var org_frame = async getPageTitle("http://example.org");

    var com_title = com_frame;
    var org_title = org_frame;
    var com_title = await com_frame;
    var org_title = await org_frame;

    print(".com: {s}, .org: {s}.\n", .{ com_title, org_title });
}

M exercises/090_async7.zig => exercises/090_async7.zig +1 -1
@@ 29,7 29,7 @@ pub fn main() void {
    // The main() function can not be async. But we know
    // getBeef() will not suspend with this particular
    // invocation. Please make this okay:
    var my_beef = getBeef(0);
    var my_beef = nosuspend getBeef(0);

    print("beef? {X}!\n", .{my_beef});
}

M exercises/091_async8.zig => exercises/091_async8.zig +4 -4
@@ 17,7 17,7 @@ pub fn main() void {

    var frame = async suspendable();

    print("X", .{});
    print("D", .{});

    resume frame;



@@ 25,11 25,11 @@ pub fn main() void {
}

fn suspendable() void {
    print("X", .{});
    print("B", .{});

    suspend {
        print("X", .{});
        print("C", .{});
    }

    print("X", .{});
    print("E", .{});
}