Merge branch 'main' into fix-060

This commit is contained in:
Chris Boesch
2026-04-07 09:18:37 +02:00
76 changed files with 1200 additions and 550 deletions

View File

@@ -0,0 +1,11 @@
--- exercises/084_async.zig 2026-04-01 20:40:08.904999609 +0200
+++ answers/084_async.zig 2026-04-01 20:40:05.641933231 +0200
@@ -37,7 +37,7 @@
const std = @import("std");
pub fn main(init: std.process.Init) !void {
- const io = init.???;
+ const io = init.io;
// Get the current wall-clock time using the Io interface.
// Hint: Timestamp.now() takes an Io and a Clock type (.real = wall clock).

View File

@@ -1,5 +1,5 @@
--- exercises/092_interfaces.zig 2023-10-03 22:15:22.125574535 +0200
+++ answers/092_interfaces.zig 2023-10-05 20:04:07.259437354 +0200
--- exercises/084_interfaces.zig 2026-04-03 19:24:51.764327692 +0200
+++ answers/084_interfaces.zig 2026-04-03 19:27:31.552579474 +0200
@@ -106,7 +106,7 @@
for (my_insects) |insect| {
// Almost done! We want to print() each insect with a

View File

@@ -0,0 +1,11 @@
--- exercises/085_async.zig 2026-04-04 16:01:01.509555724 +0200
+++ answers/085_async.zig 2026-04-04 16:00:58.541495688 +0200
@@ -38,7 +38,7 @@
const std = @import("std");
pub fn main(init: std.process.Init) !void {
- const io = init.???;
+ const io = init.io;
// Get the current wall-clock time using the Io interface.
// Hint: Timestamp.now() takes an Io and a Clock type (.real = wall clock).

View File

@@ -0,0 +1,11 @@
--- exercises/086_async2.zig 2026-04-05 12:41:11.350626443 +0200
+++ answers/086_async2.zig 2026-04-05 12:42:00.879791167 +0200
@@ -44,7 +44,7 @@
// Now collect the result. What method on Future gives us
// the value, blocking until it's ready?
- const answer = future.???(io);
+ const answer = future.await(io);
print("The answer is: {}\n", .{answer});
}

View File

@@ -0,0 +1,11 @@
--- exercises/087_async3.zig 2026-04-05 16:12:48.317265515 +0200
+++ answers/087_async3.zig 2026-04-05 16:12:52.269343030 +0200
@@ -28,7 +28,7 @@
// Launch both tasks asynchronously.
var future_a = io.async(slowAdd, .{ 1, 2 });
defer _ = future_a.cancel(io);
- var future_b = ???(slowMul, .{ 6, 7 });
+ var future_b = io.async(slowMul, .{ 6, 7 });
defer _ = future_b.cancel(io);
// Await both results.

View File

@@ -0,0 +1,11 @@
--- exercises/088_async4.zig 2026-04-06 12:22:06.643385622 +0200
+++ answers/088_async4.zig 2026-04-06 12:22:11.820491035 +0200
@@ -38,7 +38,7 @@
// Wait for all tasks to finish.
// What Group method blocks until all tasks complete?
- try group.???(io);
+ try group.await(io);
print("All tasks finished!\n", .{});
}

View File

@@ -0,0 +1,11 @@
--- exercises/089_async5.zig 2026-04-06 14:38:54.443726849 +0200
+++ answers/089_async5.zig 2026-04-06 14:38:39.945438309 +0200
@@ -46,7 +46,7 @@
// We don't want to wait 10 seconds!
// Which Future method requests cancellation AND returns the result?
- const result = future.???(io);
+ const result = future.cancel(io);
print("Task returned: {}\n", .{result});
}

View File

@@ -0,0 +1,11 @@
--- exercises/090_async6.zig 2026-04-06 18:49:37.232023422 +0200
+++ answers/090_async6.zig 2026-04-06 18:49:22.189720687 +0200
@@ -52,7 +52,7 @@
// Wait for the first finisher.
// What Select method returns the first completed result?
- const winner = try sel.???();
+ const winner = try sel.await();
switch (winner) {
.hare => |msg| print("Hare: {s}\n", .{msg}),

View File

@@ -0,0 +1,13 @@
--- exercises/091_async7.zig 2026-04-02 10:50:08.142508099 +0200
+++ answers/091_async7.zig 2026-04-02 10:49:59.629341593 +0200
@@ -49,8 +49,8 @@
for (0..times) |_| {
// Acquire the lock before modifying shared state.
// What Mutex method blocks until the lock is acquired?
- state.mutex.??? catch return;
- defer state.mutex.unlock(); // <-- what's missing here?
+ state.mutex.lock(io) catch return;
+ defer state.mutex.unlock(io);
state.counter += 1;
}

View File

@@ -0,0 +1,11 @@
--- exercises/092_async8.zig 2026-04-02 10:49:27.925721496 +0200
+++ answers/092_async8.zig 2026-04-02 10:49:31.694795212 +0200
@@ -43,7 +43,7 @@
// Send numbers 1 through 10 into the queue.
for (1..11) |i| {
// What Queue method sends a single element, blocking if full?
- queue.???(io, @intCast(i)) catch return;
+ queue.putOne(io, @intCast(i)) catch return;
}
// Signal that we're done sending.
queue.close(io);

View File

@@ -0,0 +1,11 @@
--- exercises/093_async9.zig 2026-04-06 19:26:11.388025362 +0200
+++ answers/093_async9.zig 2026-04-06 19:18:36.242931688 +0200
@@ -43,7 +43,7 @@
// Launch with a guaranteed separate unit of concurrency.
// Which Io method guarantees this?
// (Hint: unlike io.async, this one can fail!)
- var future = try io.???(compute, .{io});
+ var future = try io.concurrent(compute, .{io});
defer _ = future.cancel(io);
// Note: All breaks in this excercise (using sleep)

View File

@@ -0,0 +1,13 @@
--- exercises/094_async10.zig 2026-04-06 19:36:59.873966580 +0200
+++ answers/094_async10.zig 2026-04-06 19:37:12.416216872 +0200
@@ -51,8 +51,8 @@
// Protect this section from cancellation.
// What method swaps the cancel protection state?
- const old = io.???(.blocked);
- defer _ = io.???(old);
+ const old = io.swapCancelProtection(.blocked);
+ defer _ = io.swapCancelProtection(old);
// This sleep will NOT return error.Canceled even though
// we get canceled during it — protection is active!

View File

@@ -0,0 +1,56 @@
--- exercises/095_quiz_async.zig 2026-04-06 19:55:17.111817364 +0200
+++ answers/095_quiz_async.zig 2026-04-06 19:56:16.063974543 +0200
@@ -51,7 +51,7 @@
fn addReading(self: *GardenWeather, io: std.Io, reading: Reading) void {
// Bug 1: The collector needs to lock before modifying
// shared state. What Mutex method acquires the lock?
- self.mutex.???(io) catch return;
+ self.mutex.lock(io) catch return;
defer self.mutex.unlock(io);
switch (reading.sensor_type) {
@@ -78,7 +78,7 @@
// Bug 2: The collector needs guaranteed concurrency.
// What method ensures a separate unit of concurrency?
// (Don't forget: it can fail!)
- var collector_future = try io.???(collector, .{ io, &queue, &weather });
+ var collector_future = try io.concurrent(collector, .{ io, &queue, &weather });
defer _ = collector_future.cancel(io);
// Sensor group: the sensors can use async — they just need
@@ -91,7 +91,7 @@
// Bug 3: Wait for ALL sensors to finish sending their readings.
// What Group method blocks until all tasks complete?
- try sensors.???(io);
+ try sensors.await(io);
// All sensors done — close the queue so the collector knows
// there's no more data coming.
@@ -99,15 +99,14 @@
// Wait for the collector to drain the remaining queue.
_ = collector_future.await(io);
- // _ = collector_future.???(io);
// Now write the garden report. This is critical — it must
// NOT be interrupted, even if something tries to cancel us!
//
// Bug 5: Protect this section from cancellation.
// What Io method swaps the cancel protection state?
- const old_protection = io.???(.blocked);
- defer _ = io.???(old_protection);
+ const old_protection = io.swapCancelProtection(.blocked);
+ defer _ = io.swapCancelProtection(old_protection);
printGardenReport(&weather);
}
@@ -129,7 +128,7 @@
// Bug 6: Send the reading into the queue.
// What Queue method sends a single element?
- queue.???(io, reading) catch return;
+ queue.putOne(io, reading) catch return;
}
}

View File

@@ -1,5 +1,5 @@
--- exercises/093_hello_c.zig 2023-10-03 22:15:22.125574535 +0200
+++ answers/093_hello_c.zig 2023-10-05 20:04:07.262770750 +0200
--- exercises/096_hello_c.zig 2025-08-15 15:17:57.839348063 +0200
+++ answers/096_hello_c.zig 2026-04-03 13:09:26.195163128 +0200
@@ -54,7 +54,7 @@
//
// In this exercise we use 'write' to output 17 chars,

View File

@@ -1,11 +0,0 @@
--- exercises/097_bit_manipulation.zig 2025-05-12 21:25:03.395385743 +0200
+++ answers/097_bit_manipulation.zig 2025-05-12 21:22:57.472986976 +0200
@@ -80,7 +80,7 @@
y ^= x;
// What must be written here?
- ???;
+ x ^= y;
print("x = {b}; y = {b}\n", .{ x, y });
}

View File

@@ -1,5 +1,5 @@
--- exercises/094_c_math.zig 2024-02-28 12:50:35.789939935 +0100
+++ answers/094_c_math.zig 2024-02-28 12:53:57.910309471 +0100
--- exercises/097_c_math.zig 2025-08-15 15:17:57.839348063 +0200
+++ answers/097_c_math.zig 2026-04-03 13:09:32.059278502 +0200
@@ -26,7 +26,7 @@
const c = @cImport({

View File

@@ -1,5 +1,5 @@
--- exercises/095_for3.zig 2026-02-27 19:33:59
+++ answers/095_for3.zig 2026-02-27 19:33:38
--- exercises/098_for3.zig 2026-03-20 19:23:48.873150100 +0100
+++ answers/098_for3.zig 2026-04-03 13:09:39.916433087 +0200
@@ -56,7 +56,7 @@
// I want to print every number between 1 and 20 that is NOT

View File

@@ -1,5 +1,5 @@
--- exercises/096_memory_allocation.zig 2023-11-21 14:55:33.805678390 +0100
+++ answers/096_memory_allocation.zig 2023-11-21 14:56:00.236163484 +0100
--- exercises/099_memory_allocation.zig 2025-08-15 15:17:57.839348063 +0200
+++ answers/099_memory_allocation.zig 2026-04-03 13:09:47.403580391 +0200
@@ -64,7 +64,7 @@
const allocator = arena.allocator();

View File

@@ -0,0 +1,11 @@
--- exercises/100_bit_manipulation.zig 2025-08-15 15:17:57.839348063 +0200
+++ answers/100_bit_manipulation.zig 2026-04-02 10:51:15.795831343 +0200
@@ -80,7 +80,7 @@
y ^= x;
// What must be written here?
- ???;
+ x ^= y;
print("x = {b}; y = {b}\n", .{ x, y });
}

View File

@@ -1,5 +1,5 @@
--- exercises/098_bit_manipulation2.zig 2023-10-03 22:15:22.125574535 +0200
+++ answers/098_bit_manipulation2.zig 2023-10-05 20:04:07.286104520 +0200
--- exercises/101_bit_manipulation2.zig 2025-08-15 15:17:57.839348063 +0200
+++ answers/101_bit_manipulation2.zig 2026-04-02 10:51:15.797831382 +0200
@@ -60,5 +60,5 @@
// and if so, we know the given string is a pangram
//

View File

@@ -1,5 +1,5 @@
--- exercises/099_formatting.zig 2024-11-07 21:45:10.459123650 +0100
+++ answers/099_formatting.zig 2024-11-07 21:43:55.154345991 +0100
--- exercises/102_formatting.zig 2026-03-20 19:23:48.873150100 +0100
+++ answers/102_formatting.zig 2026-04-02 10:51:15.799831421 +0200
@@ -131,7 +131,7 @@
for (0..size) |b| {
// What formatting is needed here to make our columns

View File

@@ -1,5 +1,5 @@
--- exercises/100_for4.zig 2023-10-03 22:15:22.125574535 +0200
+++ answers/100_for4.zig 2023-10-05 20:04:07.296104707 +0200
--- exercises/103_for4.zig 2025-08-15 15:17:57.839348063 +0200
+++ answers/103_for4.zig 2026-04-02 10:51:15.801831460 +0200
@@ -39,7 +39,7 @@
const hex_nums = [_]u8{ 0xb, 0x2a, 0x77 };
const dec_nums = [_]u8{ 11, 42, 119 };

View File

@@ -1,5 +1,5 @@
--- exercises/101_for5.zig 2023-10-03 22:15:22.125574535 +0200
+++ answers/101_for5.zig 2023-10-05 20:04:07.299438103 +0200
--- exercises/104_for5.zig 2025-08-15 15:17:57.839348063 +0200
+++ answers/104_for5.zig 2026-04-02 10:51:15.803831499 +0200
@@ -51,7 +51,7 @@
// We would like to number our list starting with 1, not 0.

View File

@@ -1,5 +1,5 @@
--- exercises/102_testing.zig 2025-10-24 12:54:56
+++ answers/102_testing.zig 2025-10-24 12:56:33
--- exercises/105_testing.zig 2026-03-20 19:23:48.873150100 +0100
+++ answers/105_testing.zig 2026-04-02 10:51:15.805831538 +0200
@@ -71,7 +71,7 @@
// The corresponding test is not much different from the previous one. Except
// that it contains an error that you need to correct.

View File

@@ -1,5 +1,5 @@
--- exercises/103_tokenization.zig 2026-02-27 19:25:11
+++ answers/103_tokenization.zig 2026-02-27 19:26:04
--- exercises/106_tokenization.zig 2026-03-20 19:23:48.873150100 +0100
+++ answers/106_tokenization.zig 2026-04-02 10:51:15.807831578 +0200
@@ -134,7 +134,7 @@
;

View File

@@ -1,6 +1,6 @@
--- exercises/104_threading.zig 2025-11-28 14:17:31.552529679 +0100
+++ answers/104_threading.zig 2025-11-28 14:15:36.823931851 +0100
@@ -97,12 +97,12 @@
--- exercises/107_threading.zig 2026-04-01 23:31:10.073198955 +0200
+++ answers/107_threading.zig 2026-04-02 10:51:15.809831617 +0200
@@ -88,12 +88,12 @@
defer handle.join();
// Second thread

View File

@@ -1,5 +1,5 @@
--- exercises/105_threading2.zig 2024-03-23 16:35:14.754540802 +0100
+++ answers/105_threading2.zig 2024-03-23 16:38:00.577539733 +0100
--- exercises/108_threading2.zig 2025-08-15 15:17:57.839348063 +0200
+++ answers/108_threading2.zig 2026-04-02 10:51:15.811831656 +0200
@@ -81,8 +81,8 @@
defer handle1.join();

View File

@@ -1,5 +1,5 @@
--- exercises/106_files.zig 2026-01-09 22:41:19.373872684 +0100
+++ answers/106_files.zig 2026-01-09 22:41:44.518372910 +0100
--- exercises/109_files.zig 2026-03-20 19:23:48.874150121 +0100
+++ answers/109_files.zig 2026-04-02 10:51:15.813831695 +0200
@@ -41,7 +41,7 @@
// by doing nothing
//

View File

@@ -1,5 +1,5 @@
--- exercises/107_files2.zig 2026-01-09 22:43:15.211177186 +0100
+++ answers/107_files2.zig 2026-01-09 22:42:48.943654602 +0100
--- exercises/110_files2.zig 2026-03-20 19:23:48.874150121 +0100
+++ answers/110_files2.zig 2026-04-02 10:51:15.815831734 +0200
@@ -39,7 +39,7 @@
// initialize an array of u8 with all letter 'A'
// we need to pick the size of the array, 64 seems like a good number

View File

@@ -1,6 +1,6 @@
--- exercises/108_labeled_switch.zig 2024-09-20 12:09:24.370066539 +0200
+++ answers/108_labeled_switch.zig 2024-09-20 12:09:06.499711739 +0200
@@ -65,13 +65,13 @@
--- exercises/111_labeled_switch.zig 2025-08-15 15:17:57.840348083 +0200
+++ answers/111_labeled_switch.zig 2026-04-02 10:51:15.817831773 +0200
@@ -67,13 +67,13 @@
// how would you fix it?
pr: switch (PullRequestState.Draft) {
PullRequestState.Draft => continue :pr PullRequestState.InReview,

View File

@@ -1,5 +1,5 @@
--- exercises/109_vectors.zig 2024-11-07 14:57:09.673383618 +0100
+++ answers/109_vectors.zig 2024-11-07 14:22:59.069150138 +0100
--- exercises/112_vectors.zig 2025-08-15 15:17:57.840348083 +0200
+++ answers/112_vectors.zig 2026-04-02 10:51:15.819831812 +0200
@@ -121,8 +121,8 @@
const Vec4 = @Vector(4, f32);

View File

@@ -1,6 +1,6 @@
--- exercises/110_quiz9.zig 2025-02-08 13:19:48.522641785 -0800
+++ answers/110_quiz9.zig 2025-02-10 17:42:04.525004335 -0800
@@ -108,7 +108,7 @@
--- exercises/113_quiz9.zig 2025-08-15 15:17:57.840348083 +0200
+++ answers/113_quiz9.zig 2026-04-02 10:51:15.821831851 +0200
@@ -84,7 +84,7 @@
PORTB = 0b1100;
print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB});
print("^ {b:0>4} // (bitmask)\n", .{0b0101});
@@ -9,7 +9,7 @@
checkAnswer(0b1001, PORTB);
newline();
@@ -116,7 +116,7 @@
@@ -92,7 +92,7 @@
PORTB = 0b1100;
print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB});
print("^ {b:0>4} // (bitmask)\n", .{0b0011});
@@ -18,7 +18,7 @@
checkAnswer(0b1111, PORTB);
newline();
@@ -170,7 +170,7 @@
@@ -103,7 +103,7 @@
PORTB = 0b1001; // reset PORTB
print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB});
print("| {b:0>4} // (bitmask)\n", .{0b0100});
@@ -27,7 +27,7 @@
checkAnswer(0b1101, PORTB);
newline();
@@ -178,7 +178,7 @@
@@ -111,7 +111,7 @@
PORTB = 0b1001; // reset PORTB
print(" {b:0>4} // (reset state)\n", .{PORTB});
print("| {b:0>4} // (bitmask)\n", .{0b0100});
@@ -36,7 +36,7 @@
checkAnswer(0b1101, PORTB);
newline();
@@ -269,7 +269,7 @@
@@ -122,7 +122,7 @@
PORTB = 0b1110; // reset PORTB
print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB});
print("& {b:0>4} // (bitmask)\n", .{0b1011});
@@ -45,7 +45,7 @@
checkAnswer(0b1010, PORTB);
newline();
@@ -277,7 +277,7 @@
@@ -130,7 +130,7 @@
PORTB = 0b0111; // reset PORTB
print(" {b:0>4} // (reset state)\n", .{PORTB});
print("& {b:0>4} // (bitmask)\n", .{0b1110});

View File

@@ -1,5 +1,5 @@
--- exercises/111_packed.zig 2026-03-13 11:18:44
+++ answers/111_packed.zig 2026-03-13 11:18:57
--- exercises/114_packed.zig 2026-03-20 19:23:48.874150121 +0100
+++ answers/114_packed.zig 2026-04-02 10:51:15.824831910 +0200
@@ -41,7 +41,7 @@
const PackedStruct = packed struct {

View File

@@ -1,5 +1,5 @@
--- exercises/112_packed2.zig 2026-03-13 11:14:08
+++ answers/112_packed2.zig 2026-03-13 11:14:16
--- exercises/115_packed2.zig 2026-03-20 19:23:48.874150121 +0100
+++ answers/115_packed2.zig 2026-04-02 10:51:15.826831949 +0200
@@ -13,9 +13,9 @@
const s: S = .{ .a = true, .b = -1 };
switch (s) {