Zig is a static language without variadic parameters, so you can't make it optional in that sense. You could make the options a `?T` and pass `null` instead, but it isn't idiomatic, because passing `.{}` to a parameter expecting a `T` will fill in all the default values for you.
Arity N when you supply a value
Arity N-1 when you use the default
I can think of a few reasons
- makes function calling simpler
- faster compilation
- less symbol mangling
- makes grepping for function implementation easier
If for some reason you think you absolutely can't live without variadic functions, maybe don't use zig.
In other words, for a function f(x : T), f(.{}) is f(T()), not f(), where T() is the default constructor for type T.
If we had a function with two parameters g(x : T, y : T2) it would be g(.{}, .{}) which means g(T(), T2()), not g().
It looks like the feature exists to avoid things like:
x : really_long_type = really_long_type(), which can be replaced with x : T = .{} to avoid unnecessary duplication.
They should add default parameters to avoid this sort of thing. Maybe they ought to consider named/labelled parameters, too, if they're so concerned about clarity.
Per the article, this is the explicit form:
var gpa = std.heap.GeneralPurposeAllocator(std.heap.GeneralPurposeAllocatorConfig{}){};The fact that unacceptable parameter would fail compile time validation does not make it any more readable.
var foo = OpaqueTypeName(.{}){};
What is the . eliding?You don't know. I don't know. It's impossible to tell because the type is opaque to our understanding.
i don't know if there are other uses for . and {} that would make this hard to read. if there are, then maybe that's an issue, but otherwise, i don't see that as a problem. it's something to learn.
ideally, each syntax element has only one obvious use. that's not always possible, but as long as the right meaning can easily be inferred from the context, then that's good enough for most cases.
const a_struct: StructType = .{ .foo = "baz"};
As well as union initialization. So .{} is a struct constructor for a struct where every field has a default value, which chooses all of those fields. const a_struct: StructType = StructType{ .foo = "baz" };
const a_struct = StructType{ .foo = "baz" };
const a_struct: StructType = .{ .foo = "baz" };It's really not much different than in nearly any other language with type inference except for the dot (which is just a placeholder for an inferred type name).