I mostly share your confusion.
Doing generic data types via ‘fn (T: type, ...) type {
’ was one of Zig features I was able to understand very quickly. But anytype
is another kind of beast.
It seems anytype
is not a type at all (like u32
, type
(!!!) etc). It looks more like an instruction to the compiler - “expect argument of any type and do monomorphization for each actual type encountered in a program”.
I can do generic polymorphic addition by two ways.
with anytype
, like this:
const std = @import("std");
fn add1(a: anytype, b: @TypeOf(a)) @TypeOf(a) {
return a + b;
}
pub fn main() void {
const x: f32 = 1;
const y: f32 = 2;
std.debug.print("{}\n", .{add1(x,y)});
const j: u32 = 1;
const k: u32 = 2;
std.debug.print("{}\n", .{add1(j,k)});
}
We have two monomorphized versions:
zig-lang/anytype$ nm 1 | grep add1
000000000103c0d0 t 1.add1__anon_3427
000000000103c2b0 t 1.add1__anon_3429
with type
type:
onst std = @import("std");
fn add2(T: type, a: T, b: T) T {
return a + b;
}
pub fn main() void {
const x: f32 = 1;
const y: f32 = 2;
std.debug.print("{}\n", .{add2(@TypeOf(x),x,y)});
const j: u32 = 1;
const k: u32 = 2;
std.debug.print("{}\n", .{add2(@TypeOf(j),j,k)});
}
Again, we have two versions of the function:
zig-lang/anytype$ nm 2 | grep add2
000000000103c0d0 t 2.add2__anon_3427
000000000103c2b0 t 2.add2__anon_3429
What is the difference?
In the second case we indicate arguments’ type explicitly, in the first one it is done automatically, I think so. Correct me, if am wrong.
As to type
type and anytype
mix - I think they are orthogonal to each other.
Just because anytype
is not a name of a type.
anytype
is for “parametric polymorphism”, type
type is for generic data structures, a sort of that.