I think there is a difference in how I am able to hide API’s from the user?
If I only use the struct based imports, then I cannot hide any API’s from the user. But if I use file based imports, then I can.
For example:
// not hidden from user
pub const coe = @import("mailbox/coe.zig");
// hidden from user
const coe = @import("mailbox/coe.zig");
And if I need to have more files in my library reference coe then I need to use file-based imports?
I have been using file based imports up until this point, but I have been questioning this decision because I think I want the majority of my code to look like how a user would use it, which is only struct-based imports:
Whether you treat them as structs or namespaces doesn’t change that.
I’m guessing you’re conflating declarations and fields.
Fields can’t be private, they are always public and to access them you need an instance of the type.
Declarations are const’s var’s and functions, they are global, i.e. not tied to an instance of the type, as such you don’t need an instance to access them.
Declarations can be made public with the pub keyword, allowing them to be accessed outside the type they are declared in.
…and then all ‘cross-system-access’ happens via module-imports, e.g.:
IIRC you can’t import zig files via the parent directory anyway (e.g. const blub = @import("../bla/blub.zig") so wrapping everything into modules (which then depend on each other) is the cleaner approach anyway - and this also enforces a nice and clean hierarchical structure in your project (instead of just importing anything from anywhere).
You can as long as both files are part of the same module.
I think that bla has to be a subdirectory/underneath where the root file of the module is located, so it can’t be one of the sibling directories of the parent directory of the root file.