about things
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

arraylist#

ArrayList is zig's growable buffer - you use it when you don't know the size upfront. common for building strings, collecting results, or accumulating data before sending it somewhere.

in 0.15, arraylist became "unmanaged" - you pass the allocator to each method instead of storing it in the struct. the compiler catches missing allocators immediately, so that's not the tricky part. the tricky part is ownership.

ownership patterns#

when you build up data in an arraylist, you eventually need to do something with it. there are two paths:

build and discard - you use the data, then throw it away. this is most common (e.g., building an http response):

var buf: std.ArrayList(u8) = .empty;
defer buf.deinit(alloc);  // cleanup when we're done

try buf.print(alloc, "{s}: {d}", .{ name, value });
sendResponse(buf.items);

buf.items is the []u8 slice holding the actual data - a direct view into the arraylist's internal buffer. the arraylist still owns this memory, so don't hold onto it after deinit.

build and return - you're building something to give to a caller. they'll own the memory:

var buf: std.ArrayList(u8) = .empty;
// no defer here - we're transferring ownership

try buf.appendSlice(alloc, data);
return buf.toOwnedSlice(alloc);  // caller must free this

the key difference: .items borrows (arraylist still owns the memory, will free on deinit). .toOwnedSlice() transfers ownership (arraylist forgets about it, caller must free).

see: dashboard.zig#L187 for the return pattern

direct methods vs writer#

you might think you need to get a writer to write formatted output, but arraylist has .print() built in:

try buf.print(alloc, "{{\"count\":{d}}}", .{count});

use .writer(alloc) when you need to pass to something that expects a generic std.Io.Writer:

const w = buf.writer(alloc);
try json.stringify(value, .{}, w);

why unmanaged#

from the release notes: storing the allocator had costs - worse method signatures for reservations, can't statically initialize, extra memory for nested containers. the benefits (convenience, avoiding wrong allocator) didn't justify it since the allocator is always nearby anyway.