How to use trimLeft inside a loop

const line = "line read from somewhere";    
for (std.ascii.spaces) |v| {
    line = std.mem.trimLeft(u8, line, &[_]u8{v});
}

This snippet will report error: cannot assign to constant.

If I change const line to var line, it will report

./src/loc.zig:82:36: error: expected type '[]u8', found '[]const u8'
            line = std.mem.trimLeft(u8, line, &[_]u8{v});

I couldn’t understand how to use trimLeft inside a loop, since both its input and output is const, how could I trim a value cascadingly?

1 Like

This problem is caused by a type mismatch. This is a potentially non-trivial facet of Zig / lower level programming that you need to become familiar with to become proficient with Zig.

line needs to be a var because you plan to modify it. const declarations cannot be modified after creation.

The problem that you experience afterward has to do with the type of line and the type returned by trimLeft. In Zig string literals are constant pointers to null-terminated arrays, so without any extra specification, line will be a *const [24:0] u8, while trimLeft returns a slice ([]const u8).

A pointer to an array can coerce to a slice, but not vice-versa, which means that you can pass line to trimLeft (even if it expects a []const u8) but you can’t assign the return value to line.

The solution is to ask for line to be a slice like so:

var line: []const u8 = "foo";

The reason why string literals are not slices by default is that a pointer to an array preserves more compile-time information than a slice because a slice has a run-time known length.

For more info about string literals:

For more info about coercion between pointers, slices, etc:

4 Likes