diff options
-rw-r--r-- | CONTRIBUTING.md | 83 | ||||
-rw-r--r-- | README.md | 3 | ||||
-rw-r--r-- | build.zig | 9 | ||||
-rw-r--r-- | exercises/003_assignment.zig | 4 | ||||
-rw-r--r-- | exercises/026_hello2.zig | 1 | ||||
-rw-r--r-- | exercises/042_pointers4.zig | 11 | ||||
-rw-r--r-- | exercises/043_pointers5.zig | 41 | ||||
-rw-r--r-- | exercises/047_methods.zig | 21 | ||||
-rw-r--r-- | exercises/050_no_value.zig | 3 | ||||
-rw-r--r-- | exercises/064_builtins.zig | 40 | ||||
-rw-r--r-- | exercises/065_builtins2.zig | 2 | ||||
-rw-r--r-- | exercises/069_comptime4.zig | 2 | ||||
-rw-r--r-- | exercises/079_quoted_identifiers.zig | 2 | ||||
-rw-r--r-- | exercises/082_anonymous_structs3.zig | 2 | ||||
-rwxr-xr-x | patches/gollum.sh | 4 | ||||
-rw-r--r-- | patches/patches/042_pointers4.patch | 2 | ||||
-rw-r--r-- | patches/patches/043_pointers5.patch | 2 | ||||
-rw-r--r-- | patches/patches/047_methods.patch | 6 | ||||
-rw-r--r-- | patches/patches/064_builtins.patch | 4 |
19 files changed, 151 insertions, 91 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eb80688..7d15cc6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,79 +1,84 @@ # Contributing -By reading this document, you have already entered the Elite Hall of Ziglings -Maintenance! +By reading this document, you have already entered the Elite Hall +of Ziglings Maintenance! ## The Ziglings Audience -Ziglings is intended for programmers of all experience levels. No specific -language knowledge is expected. If you can install the current Zig snapshot, -setup a copy of Ziglings, and understand if/then/else, loops, and functions, -then you're ready. +Ziglings is intended for programmers of all experience levels. No +specific language knowledge is expected. Anyone who can install +the current Zig snapshot, setup a copy of Ziglings, and knows +common language building blocks (if/then/else, loops, and +functions) is ready or Ziglings. -Experience with strong typing, manual memory management, and certain language -constructs and idioms will greatly increase the speed at which you'll be able -to tackle each exercise. But speed isn't important, only learning is important. +Ziglings is intended to be completely self-contained. If you +can't solve an exercise from the information you've gleaned so +far from Ziglings, then the exercise probably needs some +additional work. Please file an issue! -Ziglings is intended to be completely self-contained. If you can't solve an -exercise from the information you've gleaned so far from Ziglings, then the -exercise probably needs some additional work. Please file an issue! - -If an example doesn't match a description or if something is unclear, please -file an issue! +If an example doesn't match a description or if something is +unclear, please file an issue! ## Spelling/Grammar -If you see any typos, please file an issue or make a pull request. +If you see any typos, please file an issue...or make a pull +request! -No mistake is too small. The Ziglings must be perfect. +No mistake is too small. The Ziglings must be perfect. :-) ## Ideas -If you have ideas for new lessons or a way Ziglings could be improved, don't -hesitate to file an issue. +If you have ideas for new lessons or a way Ziglings could be +improved, don't hesitate to file an issue. -I prefer to actually write all of the content myself at this time (part of the -reason I'm building Ziglings is to learn Zig myself!), but I'm always open to -ideas. +I prefer to write the bulk of the content myself at this time +(part of the reason I'm building Ziglings is to learn Zig +myself!), but I'm always open to ideas. ## Platforms and Zig Versions -Because it uses the Zig build system, Ziglings should work wherever Zig does. +Because it uses the Zig build system, Ziglings should work +wherever Zig does. -Since Ziglings is a Zig language learning resource, it tracks the current -development of Zig. +Since Ziglings is a Zig language learning resource, it tracks the +current development snapshots of Zig from the official website +downloads page. -If you run into an error in Ziglings due to language changes (and you have the -latest development build of Zig and the latest commit to Ziglings), that's a -bug! Please file an issue. +If you run into an error in Ziglings caused by breaking changes +in the latest development build of Zig, that's a new bug in +Ziglings. Please file an issue...or make a pull request! ## Formatting -All exercises are (or should be) formatted with `zig fmt`. +All exercises should conformt to `zig fmt`. I often forget to do +this. ## Pull Request Workflow -Ziglings uses the "standard" Github workflow as guided by the Web interface. -Specifically: +Ziglings uses the "standard" Github workflow as guided by the Web +interface. Specifically: * Fork this repository -* Create a branch from `main` for your work: `git checkout -b my-branch` +* Create a branch from `main` for your work: + `git checkout -b my-branch` * Make changes, commit them -* When your changes are ready for review, push your branch: `git push origin - my-branch` +* When your changes are ready for review, push your branch: + `git push origin my-branch` * Create a pull request from your branch to `ziglings/main` -* Your faithful Ziglings maintainer "ratfactor" (that's me!) will take a look - at your request ASAP -* Once the changes are reviewed, your request will be merged and eternal - Ziglings contributor glory is yours! +* Your faithful Ziglings maintainer "ratfactor" (that's me!) will + take a look at your request ASAP (we don't talk about May-July + 2022, LOL) +* Once the changes are reviewed, your request will be merged and + eternal Ziglings contributor glory is yours! ## The Secrets -If you want to peek at the secrets, take a look at the `patches/` directory. +If you want to peek at the secrets, take a look at the `patches/` +directory. @@ -41,7 +41,7 @@ Verify the installation and build number of `zig` like so: ```bash $ zig version -0.10.0-dev.1427+xxxxxxxxx +0.10.0-dev.3385+xxxxxxxxx ``` Clone this repository with Git: @@ -81,6 +81,7 @@ about input: ### Version Changes +* *2022-07-31* zig 0.10.0-dev.3385 - std lib string fmt() option changes * *2022-03-19* zig 0.10.0-dev.1427 - method for getting sentinel of type changed * *2021-12-20* zig 0.9.0-dev.2025 - `c_void` is now `anyopaque` * *2021-06-14* zig 0.9.0-dev.137 - std.build.Id `.Custom` is now `.custom` @@ -8,7 +8,7 @@ const print = std.debug.print; // When changing this version, be sure to also update README.md in two places: // 1) Getting Started // 2) Version Changes -const needed_version = std.SemanticVersion.parse("0.10.0-dev.1427") catch unreachable; +const needed_version = std.SemanticVersion.parse("0.10.0-dev.3385") catch unreachable; const Exercise = struct { /// main_file must have the format key_name.zig. @@ -64,7 +64,7 @@ const exercises = [_]Exercise{ }, .{ .main_file = "004_arrays.zig", - .output = "Fourth: 7, Length: 8", + .output = "First: 2, Fourth: 7, Length: 8", .hint = "There are two things to complete here.", }, .{ @@ -240,7 +240,8 @@ const exercises = [_]Exercise{ }, .{ .main_file = "043_pointers5.zig", - .output = "Wizard (G:10 H:100 XP:20)", + .output = "Wizard (G:10 H:100 XP:20)\n Mentor: Wizard (G:10000 H:100 XP:2340)", + }, .{ .main_file = "044_quiz5.zig", @@ -331,7 +332,7 @@ const exercises = [_]Exercise{ }, .{ .main_file = "064_builtins.zig", - .output = "1101 + 0101 = 0010 (true). Furthermore, 11110000 backwards is 00001111.", + .output = "1101 + 0101 = 0010 (true). Without overflow: 00010010. Furthermore, 11110000 backwards is 00001111.", }, .{ .main_file = "065_builtins2.zig", diff --git a/exercises/003_assignment.zig b/exercises/003_assignment.zig index 6a4364b..10ba8cb 100644 --- a/exercises/003_assignment.zig +++ b/exercises/003_assignment.zig @@ -12,7 +12,7 @@ // var bar: u8 = 20; // // Example: foo cannot be negative and can hold 0 to 255 -// bar CAN be negative and can hold −128 to 127 +// bar CAN be negative and can hold -128 to 127 // // const foo: u8 = 20; // const bar: i8 = -20; @@ -26,7 +26,7 @@ // You can do just about any combination of these that you can think of: // // u32 can hold 0 to 4,294,967,295 -// i64 can hold −9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 +// i64 can hold -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 // // Please fix this program so that the types can hold the desired values // and the errors go away! diff --git a/exercises/026_hello2.zig b/exercises/026_hello2.zig index 237d27c..cb29193 100644 --- a/exercises/026_hello2.zig +++ b/exercises/026_hello2.zig @@ -10,7 +10,6 @@ const std = @import("std"); // that Zig will infer the error type. This is appropriate in the case // of main(), but can have consequences elsewhere. pub fn main() !void { - // We get a Writer for Standard Out so we can print() to it. const stdout = std.io.getStdOut().writer(); diff --git a/exercises/042_pointers4.zig b/exercises/042_pointers4.zig index 261dbc1..359a2f1 100644 --- a/exercises/042_pointers4.zig +++ b/exercises/042_pointers4.zig @@ -1,6 +1,15 @@ // // Now let's use pointers to do something we haven't been -// able to do before: pass a value by reference to a function! +// able to do before: pass a value by reference to a function. +// +// Why would we wish to pass a pointer to an integer variable +// rather than the integer value itself? Because then we are +// allowed to *change* the value of the variable! +// +// +-----------------------------------------------+ +// | Pass by reference when you want to change the | +// | pointed-to value. Otherwise, pass the value. | +// +-----------------------------------------------+ // const std = @import("std"); diff --git a/exercises/043_pointers5.zig b/exercises/043_pointers5.zig index ae80ecc..9e2fa6f 100644 --- a/exercises/043_pointers5.zig +++ b/exercises/043_pointers5.zig @@ -1,8 +1,7 @@ // -// Passing integer pointers around is generally not something you're going -// to do. Integers are cheap to copy. -// -// But you know what IS useful? Pointers to structs: +// As with integers, you can pass a pointer to a struct when you +// will wish to modify that struct. Pointers are also useful when +// you need to store a reference to a struct (a "link" to it). // // const Vertex = struct{ x: u32, y: u32, z: u32 }; // @@ -16,7 +15,8 @@ // YES: pv.x // NO: pv.*.x // -// We can write functions that take pointer arguments: +// We can write functions that take pointers to structs as +// arguments. This foo() function modifies struct v: // // fn foo(v: *Vertex) void { // v.x += 2; @@ -24,13 +24,13 @@ // v.z += 7; // } // -// And pass references to them: +// And call them like so: // // foo(&v1); // -// // Let's revisit our RPG example and make a printCharacter() function -// that takes a Character pointer. +// that takes a Character by reference and prints it...*and* +// prints a linked "mentor" Character, if there is one. // const std = @import("std"); @@ -44,25 +44,35 @@ const Class = enum { const Character = struct { class: Class, gold: u32, - health: u8 = 100, // <--- You can also provide fields a default value! + health: u8 = 100, // You can provide default values experience: u32, + + // I need to use the '?' here to allow for a null value. But + // I don't explain it until later. Please don't tell anyone. + mentor: ?*Character = null, }; pub fn main() void { - var glorp = Character{ + var mighty_krodor = Character{ + .class = Class.wizard, + .gold = 10000, + .experience = 2340, + }; + + var glorp = Character{ // Glorp! .class = Class.wizard, .gold = 10, .experience = 20, + .mentor = &mighty_krodor, // Glorp's mentor is the Mighty Krodor }; // FIX ME! - // Please pass our Character "glorp" to printCharacter(): + // Please pass Glorp to printCharacter(): printCharacter(???); } // Note how this function's "c" parameter is a pointer to a Character struct. fn printCharacter(c: *Character) void { - // Here's something you haven't seen before: when switching an enum, you // don't have to write the full enum name. Zig understands that ".wizard" // means "Class.wizard" when we switch on a Class enum value: @@ -79,4 +89,11 @@ fn printCharacter(c: *Character) void { c.health, c.experience, }); + + // Checking an "optional" value and capturing it will be + // explained later (this pairs with the '?' mentioned above.) + if (c.mentor) |mentor| { + std.debug.print(" Mentor: ", .{}); + printCharacter(mentor); + } } diff --git a/exercises/047_methods.zig b/exercises/047_methods.zig index aee4c16..0e7bfa8 100644 --- a/exercises/047_methods.zig +++ b/exercises/047_methods.zig @@ -10,7 +10,7 @@ // pub fn hello() void { // std.debug.print("Foo says hello!\n", .{}); // } -// } +// }; // // 2. A function that is a member of a struct is a "method" and is // called with the "dot syntax" like so: @@ -23,10 +23,10 @@ // const Bar = struct{ // number: u32, // -// pub fn printMe(self: *Bar) void { +// pub fn printMe(self: Bar) void { // std.debug.print("{}\n", .{self.number}); // } -// } +// }; // // (Actually, you can name the first parameter anything, but // please follow convention and use "self".) @@ -55,10 +55,15 @@ const Alien = struct { .health = strength * 5, }; } +}; + +// Your trusty weapon. Zap those aliens! +const HeatRay = struct { + damage: u8, // We love this method: - pub fn zap(self: *Alien, damage: u8) void { - self.health -= if (damage >= self.health) self.health else damage; + pub fn zap(self: *HeatRay, alien: *Alien) void { + alien.health -= if (self.damage >= alien.health) alien.health else self.damage; } }; @@ -74,7 +79,7 @@ pub fn main() void { }; var aliens_alive = aliens.len; - var heat_ray_strength: u8 = 7; // We've been given a heat ray weapon. + var heat_ray = HeatRay{ .damage = 7 }; // We've been given a heat ray weapon. // We'll keep checking to see if we've killed all the aliens yet. while (aliens_alive > 0) { @@ -83,8 +88,8 @@ pub fn main() void { // Loop through every alien by reference (* makes a pointer capture value) for (aliens) |*alien| { - // *** Zap the Alien Here! *** - ???.zap(heat_ray_strength); + // *** Zap the alien with the heat ray here! *** + ???.zap(???); // If the alien's health is still above 0, it's still alive. if (alien.health > 0) aliens_alive += 1; diff --git a/exercises/050_no_value.zig b/exercises/050_no_value.zig index 8708d2d..8c73ed3 100644 --- a/exercises/050_no_value.zig +++ b/exercises/050_no_value.zig @@ -71,7 +71,8 @@ pub fn main() void { var first_line2: Err!*const [21]u8 = ???; first_line2 = "which can eternal lie"; - std.debug.print("{s} {s} / ", .{ first_line1, first_line2 }); + // Note we need the "{!s}" format for the error union string. + std.debug.print("{s} {!s} / ", .{ first_line1, first_line2 }); printSecondLine(); } diff --git a/exercises/064_builtins.zig b/exercises/064_builtins.zig index 508f8ed..018bf95 100644 --- a/exercises/064_builtins.zig +++ b/exercises/064_builtins.zig @@ -41,22 +41,38 @@ pub fn main() void { var my_result: u4 = undefined; var overflowed: bool = undefined; overflowed = @addWithOverflow(u4, a, b, &my_result); - // + + // Check out our fancy formatting! b:0>4 means, "print + // as a binary number, zero-pad right-aligned four digits." // The print() below will produce: "1101 + 0101 = 0010 (true)". - // Let's make sense of this answer by counting up from 1101: + print("{b:0>4} + {b:0>4} = {b:0>4} ({})", .{ a, b, my_result, overflowed }); + + // Let's make sense of this answer. The value of 'b' in decimal is 5. + // Let's add 5 to 'a' but go one by one and see where it overflows: // - // Overflowed? - // 1101 + 1 = 1110 No. - // 1110 + 1 = 1111 No. - // 1111 + 1 = 0000 Yes! (Real answer is 10000) - // 0000 + 1 = 0001 No. - // 0001 + 1 = 0010 No. + // a | b | result | overflowed? + // ---------------------------------- + // 1101 + 0001 = 1110 | false + // 1110 + 0001 = 1111 | false + // 1111 + 0001 = 0000 | true (the real answer is 10000) + // 0000 + 0001 = 0001 | false + // 0001 + 0001 = 0010 | false // - // Also, check out our fancy formatting! b:0>4 means, "print - // as a binary number, zero-pad right-aligned four digits." - print("{b:0>4} + {b:0>4} = {b:0>4} ({})", .{ a, b, my_result, overflowed }); + // In the last two lines the value of 'a' is corrupted because there was + // an overflow in line 3, but the operations of lines 4 and 5 themselves + // do not overflow. + // There is a difference between + // - a value, that overflowed at some point and is now corrupted + // - a single operation that overflows and maybe causes subsequent errors + // In practise we usually notice the overflowed value first and have to work + // our way backwards to the operation that caused the overflow. + // + // If there was no overflow at all while adding 5 to a, what value would + // 'my_result' hold? Write the answer in into 'expected_result'. + const expected_result: u8 = ???; + print(". Without overflow: {b:0>8}. ", .{expected_result}); - print(". Furthermore, ", .{}); + print("Furthermore, ", .{}); // Here's a fun one: // diff --git a/exercises/065_builtins2.zig b/exercises/065_builtins2.zig index 1532c2a..d50b6f0 100644 --- a/exercises/065_builtins2.zig +++ b/exercises/065_builtins2.zig @@ -121,7 +121,7 @@ pub fn main() void { // Alas, we can't use a regular 'for' loop here because // 'fields' can only be evaluated at compile time. It seems // like we're overdue to learn about this "comptime" stuff, - // isn't it? :-) + // doesn't it? :-) print(".\n", .{}); } diff --git a/exercises/069_comptime4.zig b/exercises/069_comptime4.zig index ecec2ee..004a42c 100644 --- a/exercises/069_comptime4.zig +++ b/exercises/069_comptime4.zig @@ -7,7 +7,7 @@ // In fact, types are ONLY available at compile time, so the // 'comptime' keyword is required here. // -// Please take a moment put on the wizard hat which has been +// Please take a moment to put on the wizard hat which has been // provided for you. We're about to use this ability to implement // a generic function. // diff --git a/exercises/079_quoted_identifiers.zig b/exercises/079_quoted_identifiers.zig index 9ef22b0..182c7ff 100644 --- a/exercises/079_quoted_identifiers.zig +++ b/exercises/079_quoted_identifiers.zig @@ -22,7 +22,7 @@ const print = @import("std").debug.print; pub fn main() void { const 55_cows: i32 = 55; const isn't true: bool = false; - + print("Sweet freedom: {}, {}.\n", .{ 55_cows, isn't true, diff --git a/exercises/082_anonymous_structs3.zig b/exercises/082_anonymous_structs3.zig index 1214589..8344321 100644 --- a/exercises/082_anonymous_structs3.zig +++ b/exercises/082_anonymous_structs3.zig @@ -116,7 +116,7 @@ fn printTuple(tuple: anytype) void { // @field(foo, "x"); // returns the value at foo.x // // The first field should print as: "0"(bool):true - print("\"{s}\"({s}):{any} ", .{ + print("\"{s}\"({any}):{any} ", .{ field.???, field.???, ???, diff --git a/patches/gollum.sh b/patches/gollum.sh index 495aa44..74f7626 100755 --- a/patches/gollum.sh +++ b/patches/gollum.sh @@ -22,7 +22,9 @@ p=patches/patches/$f.patch if [ ! -f $b ]; then echo "No $f! We hates it!"; exit 1; fi if [ ! -f $a ]; then echo "No $a! Where is it? Where is the answer, precious?"; exit; fi -echo "Hissss!\tbefore: '$b'\n\t after: '$a'\n\t patch: '$p'\n" +echo "Hissss! before: '$b'" +echo " after: '$a'" +echo " patch: '$p'" diff $b $a > $p diff --git a/patches/patches/042_pointers4.patch b/patches/patches/042_pointers4.patch index 29ca2d0..8e21b81 100644 --- a/patches/patches/042_pointers4.patch +++ b/patches/patches/042_pointers4.patch @@ -1,4 +1,4 @@ -31c31 +40c40 < ??? = 5; // fix me! --- > x.* = 5; // fix me! diff --git a/patches/patches/043_pointers5.patch b/patches/patches/043_pointers5.patch index 8a73551..ac6a8ca 100644 --- a/patches/patches/043_pointers5.patch +++ b/patches/patches/043_pointers5.patch @@ -1,4 +1,4 @@ -60c60 +71c71 < printCharacter(???); --- > printCharacter(&glorp); diff --git a/patches/patches/047_methods.patch b/patches/patches/047_methods.patch index 81e733b..edd9db1 100644 --- a/patches/patches/047_methods.patch +++ b/patches/patches/047_methods.patch @@ -1,4 +1,4 @@ -87c87 -< ???.zap(heat_ray_strength); +92c92 +< ???.zap(???); --- -> alien.zap(heat_ray_strength); +> heat_ray.zap(alien); diff --git a/patches/patches/064_builtins.patch b/patches/patches/064_builtins.patch index 644128b..06fa735 100644 --- a/patches/patches/064_builtins.patch +++ b/patches/patches/064_builtins.patch @@ -1,4 +1,8 @@ 72c72 +< const expected_result: u8 = ???; +--- +> const expected_result: u8 = 0b00010010; +88c88 < const tupni: u8 = @bitReverse(input); --- > const tupni: u8 = @bitReverse(u8, input); |