#Beginner dynamic dispatch questions
1 messages · Page 1 of 1 (latest)
Also, I prefixed some struct fields with _ as you do in python to show they are not public, is there an established way to do this in zig?
Have a look on Allocator and Failing allocator vtable impl.
Next time, paste the code inline or use zigbin.io so people don't need to download random files on their computers.
Not really, but using the _ prefix is commonly recommended for that.
Looking at your impl, looks entirely okay for me. Maybe I'd wrap overrided functions in a struct but that's only the matter of organizing self-contained code.
Awesome, thanks for the help!
As pachde wrote, underscore isn't really used as a standard. You can infer if field is public if it has a docstring (at least that's how std does it I reckon).
Not used in std, that is. I've seen it commonly recommended. Lack of docstring is ok for a project as disciplined as std, but tricky in many projects due to the, alas common, lazy approach/hostility to documentation. I prefer something more explicit than an omission.
Ah, yeah, should've communicated that clearer. I'm too new in the community so I trust your judgement more.
A doc comment saying you probably shouldn’t touch it is what I do
In your read_byte() and write_byte() self can be self: Source. No need for a pointer. Zig isn't like C, it will automatically generate code to pass by reference if the struct size is large or pass by value if the struct size is small. Took me some time to figure this out, coming from C/C++ as well.
You really only need *Source if:
- you intend to modify it's values.
- you intend to store the pointer in some long lived data structure so therefore require the reference.
Otherwise just use self: Source.
Here is an example:
const std = @import("std");
const expect = std.testing.expect;
// This is a structure that has 100 bytes of data.
const BigStruct = struct {
// Initialize to zeroes.
data: [100]u8 = [1]u8{0} ** 100,
// No need for pointer. The compiler will auto generate code to pass by value
// or ref depending on size.
// In this case it will pass by ref (ptr) because data is 100 bytes
// Note that self is const. We cannot modify it's contents.
//
fn get(self: BigStruct, pos: usize) u8 {
return self.data[pos];
}
// When we want to modify the contents, we use explicit pointer.
//
fn set(self: *BigStruct, pos: usize, val: u8) void {
self.data[pos] = val;
}
// This will not compile.
// Parameter value is constant. Zig will not let us modify the data.
//
fn clear(self: BigStruct) void {
@memset(&self.data, 0);
}
};
test "test" {
var data = BigStruct { };
data.set(0, 0xff);
try expect(data.get(0)==0xff);
// Uncomment this will error in clear():
// error: cannot memset constant pointer
// data.clear();
}
Not true in the not too far future https://github.com/ziglang/zig/issues/5973#issuecomment-2380332493
Minor addition to previous comments. OpqaueCtx is a bit superfluous, it's perfectly fine to just use *anyopaque.
Ah ok, thanks for the info!! I will keep that in mind as I am learning the language.