In Ziglings we have some exercises with array multiplication. Since it is removed from Zig, I switched to @splat(). But for exercise 005_arrays2 it doesn’t look nice.
Since that exercise is (at least currently) about array operators, and that operator no longer exists, I would personally just remove it. Maybe add @splat to the built-ins exercise?
I will take that into consideration. In this exercise there is also the ++ operator, that is still available. The next problem I encountered is:
// Use the array repeat '**' operator to make "ha ha ha ".
const laugh = "ha " ** 3;
I’ll probably have to delete that, because I can’t think of a suitable replacement. It’s a shame; I always found these operators very elegant and can’t quite understand why they’re being discontinued.
I agree with the commenter in the GitHub issue thread that the old behavior of ** would better be moved to a built-in @repeat, and that scope creep of @splat is suboptimal.
Never much liked ** for array multiplication on the syntax level, though. So it’s harder to argue against its removal.
I too like the idea of @repeat and @concat, with the added benefit of being able to control formatting with trailing commas. But rarely needed so I think comptime blk’s are fine.
Oh, just for sharing. I happened to come across this exercise two days ago. After knowing ** has been removed for only 20 hours, I repeatedly used ++ for three times manually for it.
And now, because I still regard built-in functions as magic, I’m considering whether using undefined with inline for is more explicit.
btw, I’m learning zig with ziglings, I find it so helpful. Thank you!!
Even common and core functionality uses builtin functions, such as casting (e.g. @intCast) and importing (i.e. @import), so hopefully that will help the feeling of them being magic to dissipate.
@splat provides a more ergonomic way to do what people were mostly using ** for. Features need to actively justify their existence in the language, and nobody piped up with a sufficiently convincing use case for **, so it got removed. Ziglings is designed to teach the language, so the exercises are small examples that don’t necessarily represent real usage. In this case, I think it’s reasonable to just remove this ziglings exercise.
++ is used extensively in real code, so I wouldn’t worry about its removal.
If someone needs this kind of thing, as a one off I would do:
const bit_pattern = blk: {
const pattern = [_]u8{ 1, 0, 0, 1 };
const pattern_2 = pattern ++ pattern;
// repeat as many doublings as are needed.
break :blk pattern ++ pattern_2; // binary of final number
};
and if for some reason your code actually needs to do this a lot, then a userland implementation is reasonable:
I like to set the total size instead of pattern.len * count so I use this:
fn arrayFromPattern(comptime T: type, pattern: []const std.meta.Child(T)) T {
var arr: T = undefined;
var i: usize = 0;
while (i < arr.len) : (i += pattern.len) {
const len = @min(arr.len - i, pattern.len);
@memcpy(arr[i..][0..len], pattern[0..len]);
}
return arr;
}
const arr = arrayFromPattern([5]i32, &.{ 1, 2, 3 }); // <-- {1, 2, 3, 1, 2}
// I would love this but there is no way to make this...
const arr: [5]i32 = arrayFromPattern(&.{ 1, 2, 3 });