Why not something like this?
fn feed(animal: anytype) void {
if (requires {
animal.eat();
}) {
@compileError("Type '" ++ @typeName(@TypeOf(animal)) ++ "' does not satisfy the function requirements of 'feed'");
}
animal.eat();
}
The requires expression would just return if the block is able to compile or not (via a boolean).
That could even work for something like this:
const Vector = struct {
x: i32,
y: i32,
z: i32,
};
fn move(object: anytype, vector: Vector) void {
if (requires {
object.*.x += vector.x;
object.*.y += vector.y;
object.*.z += vector.z;
}) {
@compileError("Type '" ++ @typeName(@TypeOf(object)) ++ "' is not a pointer to a mutable object with x, y and z coordinates");
}
object.*.x += vector.x;
object.*.y += vector.y;
object.*.z += vector.z;
}
(To prevent code duplication one could put the actual function implementation into another function.)
At its core, anytype is really only nice syntax over fn func(T: type, parameter: T) void, at least as far as a Zig programmer is concerned. Because of DX that’s imo even a necessary thing (think of if you would need to use the long syntax for print calls).
And this is really just unconstrained C++ templates with a more uniform syntax:
template<typename T>
void func(T parameter);
And because of that I do think that Zig needs something to constrain things too, because this has the same problems unconstrained C++ templates have (over constrained ones). And being able to chose compile time over runtime polymorphism is needed in some problem domains (even if it’s at the sacrifice of a bigger binary). Besides the fact that well implemented tooling gives imo a better DX for compile time polymorphism than for runtime polymorphism.
Chasing down a bug into a runtime interface is just a lot more annoying than if you are dealing with monomorphism, independent of the language.
And what I threw into the room here (which is essentially just requires expressions from C++20) would make it at the very least easier for programmers to chose different implementations depending on the parameters. So essentially explicit compile time overloading.
But I guess we’ll see what the core team will do about it (which hopefully will be something instead of nothing, even if they currently seem to prefer runtime polymorphism, judging from the last few releases and the last few accepted proposals).