orhun / personal-blog

The source of my blog ✍🏼
https://blog.orhun.dev
27 stars 3 forks source link

https://blog.orhun.dev/zig-bits-02/ #13

Open utterances-bot opened 1 year ago

utterances-bot commented 1 year ago

Orhun's Blog

FOSS • Linux • Programming

https://blog.orhun.dev/zig-bits-02/

digeratus commented 1 year ago

Great post Orhun. I was trying to figure out how to deal with this a few weeks ago. Quick question... keep in mind I'm still new to Zig... Is this line for the allocator missing a closing param?

var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};

Thanks again for the post.

orhun commented 1 year ago

Thank you @digeratus!

Is this line for the allocator missing a closing param?

What exactly do you mean by "closing param"?

FWIW I took that example code from the Zig documentation.

digeratus commented 1 year ago

Isn't it missing a ")" at the end before you finish the variable assignment?

std.heap.GeneralPurposeAllocator(.{}){}<isn't missing a parenthesis here>;
digeratus commented 1 year ago

Disregard. I think I see my misunderstanding.

sskras commented 1 year ago

Folks, so what does the trailing {} symbols mean there, right after the GeneralPurposeAllocator() ?

orhun commented 1 year ago

Good question. If we look at the signature of GeneralPurposeAllocator:

fn GeneralPurposeAllocator(comptime config: Config) type

We can see that it returns a generic struct (type). In that case, the curly braces after the function call mean that we can override the fields of that struct.

pub fn GeneralPurposeAllocator(comptime config: Config) type {
    return struct {
        backing_allocator: Allocator = std.heap.page_allocator,
        buckets: [small_bucket_count]?*BucketHeader = [1]?*BucketHeader{null} ** small_bucket_count,
        ...

Like so:

var gpa = GeneralPurposeAllocator(.{}){ .backing_allocator = std.testing.allocator };
kivikakk commented 1 year ago

To be a little more precise, GeneralPurposeAllocator(…) returns a new type — a struct-based one (as opposed to enum-based or whatever). You could decompose it like this:

// See https://github.com/ziglang/zig/blob/5d63d1115f0f18984ed7c517c2d85224aa4da444/lib/std/heap/general_purpose_allocator.zig#L115-L156 for what can go in this "Config" parameter.
// Note these configuration options are comptime values — they can influence the code generated for the GPA.
const MyGPAType = std.heap.GeneralPurposeAllocator(.{ .safety = false });

pub fn main() !void {
    // Here we can configure a different set of properties, these changeable at runtime.
    var gpa = MyGPAType{ .backing_allocator = std.testing.allocator };
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // … etc.
}

So std.heap.GeneralPurposeAllocator(.{}){} creates a new type (returned from the call to GeneralPurposeAllocator(…)), then instantiates one copy of it (with {}, accepting all default values for the struct type itself).

sskras commented 1 year ago

Folks, thank you both!