I’ve been used to finding the size of slices with .len - but I recently worked on a problem that required a Set. Since Zig doesn’t have one, I took the advice there to (ab)use a HashMap('s keys) instead. HashMap doesn’t have a .keys() returning a slice, only a .keyIterator() - and I noticed that .keyIterator().len does not, in fact, return the size of the map, since this test fails:
const std = @import("std");
const print = std.debug.print;
const expect = std.testing.expect;
test "Len of an iterator is not the same as size" {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
var map = std.AutoHashMap(u8, u8).init(allocator);
try map.put('a', 'b');
try map.put('c', 'd');
try map.put('e', 'f');
var keyIterator = map.keyIterator();
const length = keyIterator.len;
var counted_length: usize = 0;
while (keyIterator.next()) |_| {
counted_length += 1;
}
print("DEBUG - length is {} and counted_length is {}\n", .{ length, counted_length });
try expect(length == counted_length);
}
What is the meaning of an Iterator’s len? I looked here but didn’t find an explanation - sorry if I missed some better documentation, I’m still very new to the language!
I’m pretty sure that’s “private”, meaning they don’t expect us to touch it. Reading the implementation, it’s just the number of elements potentially remaining to iterate, but it’s not accurate, because it does a check to the element before returning.
Not great in my opinion, but as @LucasSantos91 says, it might be private. Typically you can assume that an iterator doesn’t have a known length, as you just have to iterate until you get all the keys.
There is the count() function on HashMaps that returns the number of items in the map.
Edit:
Yeah Looking at count(), I had assumed it just looped over the elements, but it is just an accessor to the size field of the HashMap. Perhaps there’s a good reason for it, but I think it would be good to rename len to capacity to reflect that. Everywhere else len is differentiated from capactiy.
sets in zig are often hash maps with a void value type.
if you prefer to be able to iterate keys with a for loop instead of an iterator, try std.AutoArrayHashMap() which has keys() and values() methods which return slices.