Sorry, folks, I’m still not getting it. Here’s a simpler example (inspired by, but simplified from, Day 14 of Advent Of Code):
const std = @import("std");
const print = std.debug.print;
const expect = @import("std").testing.expect;
const Point = struct { x: u32, y: u32 };
const Robot = struct {
position: Point,
pub fn move_right(self: *Robot) void {
self.position = Point{ .x = self.position.x + 1, .y = self.position.y };
}
pub fn from_line(line: []const u8) !Robot {
const position_of_comma = std.mem.indexOf(u8, line, ",").?;
const x = try std.fmt.parseInt(u32, line[0..position_of_comma], 10);
const y = try std.fmt.parseInt(u32, line[position_of_comma + 1 ..], 10);
return Robot{ .position = Point{ .x = x, .y = y } };
}
};
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Pretend that this string was being read from a file.
const input_data = "2,3\n10,0";
var it = std.mem.splitScalar(u8, input_data, '\n');
var robots = std.ArrayList(Robot).init(allocator);
defer robots.deinit();
while (it.next()) |line| {
try robots.append(try Robot.from_line(line));
}
for (robots.items) |robot| {
robot.move_right();
}
try expect(robots.items[0].position.x == 3);
try expect(robots.items[1].position.x == 11);
}
(fiddle)
The above gives an error as robot.move_right()
expected type '*<uuid>.Robot', found '*const <uuid>.Robot'
.
If I duly change the signature of move_right
to accept a *const Robot
, (fiddle), I then get an error on the self.position = Point{...
line, stating cannot assign to constant
.
So, it seems like I’m stuck - the value returned from my “constructor” function (from_line
) is const
, which means that any functions I pass it into have to accept a const
, which means that they cannot mutate any of its fields, and I don’t see any syntax that allows me to declare the return type of the function as var
. What am I missing?
EDIT: explicitly, it looks like I can’t declare the robot
s as variable like so:
while (it.next()) |line| {
var robot = try Robot.from_line(line)
try robots.append(robot);
}
because this, rightly, complains that local variable is never mutated
EDIT2:
You’re taking a pointer to a temporary. Pointers to temporaries are const. Make the
FibonacciMemoizer{...}
a separate variable if you need to take the address of it
I don’t understand this, nor how it applies here. What is a “temporary”? The few usages of that word in the documentation mostly don’t appear to apply here - and while Result Locations seem like they might be relevant, I don’t follow how to apply that information here. This thread also uses the term, but doesn’t seem to define it. This discussion suggests that a temporary variable is one that goes out of scope, but I don’t see how that would be the case here - each robot
is created within the body of main
, so I don’t see how they would go out-of-scope before the end of the program.