3 ms·
The post is about a specific language. The way that you write the loop without being able to mutate the elements in this language is like this: for (items) |
by anonymoushn 3y ago
The post is about a specific language. The way that you write the loop without being able to mutate the elements in this language is like this:
for (items) |item| {
}
The way that you write the loop so that you can mutate the elements is like this:
for (items) |*item| {
}
A way that you could try writing the loop so that it's clear that the elements are not mutated, even though you are using the pointer syntax, is maybe like this:
for (items) |*_item| {
const item: *const @typeInfo(@TypeOf(_item)).Pointer.child = _item;
// there's no "drop _item" so unfortunately _item remains in scope but we promise not to use it.
}
I wasn't sure this would work, but it looks like you can also manage with this:
const _items: []const @typeInfo(@TypeOf(items)).Pointer.child = items;
for (_items) |*item| {
// now item is of the correct type, even if items is a slice of mutable things.
}
- loeg 3y agoIf Zig does not have a |*const item| syntax, maybe adding it would be a good idea (and also satisfy your concern)? (Zig already has a concept of mutable and const pointers.) For example, in C++ I would distinguish between mutating iteration and non-mutating iteration like this: for (const auto& item : collection) {} // non-mutating for (auto& item : collection) {} // mutating
- jrockway 3y ago> there's no "drop _item" so unfortunately _item remains in scope but we promise not to use it This is actually a very intriguing programming language keyword. I feel like there are lots of cases where you don't want to split something into a separate function just to avoid being able to use a variable that was used previously, and these things often get refactored over time to the point where the not-to-be-used variable gets used unexpectedly.