From dee6a96ddfc043d8b2c0261cc1e54600a1d0f774 Mon Sep 17 00:00:00 2001 From: Dave Gauer Date: Sun, 31 Jul 2022 15:57:20 -0400 Subject: [PATCH] Correct conventional Zig reference vs value passing re #89 --- build.zig | 3 ++- exercises/042_pointers4.zig | 11 +++++++- exercises/043_pointers5.zig | 40 +++++++++++++++++++++-------- exercises/047_methods.zig | 6 ++--- patches/gollum.sh | 4 ++- patches/patches/042_pointers4.patch | 2 +- patches/patches/043_pointers5.patch | 2 +- 7 files changed, 49 insertions(+), 19 deletions(-) diff --git a/build.zig b/build.zig index 43af404..1c28d62 100644 --- a/build.zig +++ b/build.zig @@ -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", 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 f3a9ca0..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,19 +44,30 @@ 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(???); } @@ -78,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 048cfa0..a3ed220 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".) 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);