User-friendlines of `anytype`

I agree with the sentiment that anytype is not user-friendly, but it is superior in terms of performance. When Reader changed to anytype, the codegen of my project got a lot better. Devirtualization is a myth. Unless you’re doing some very trivial aliasing, like declaring a pointer and then immediately using it, it’s not going to happen.
If you’ve used Zig for some time, you know what to do when a function takes a parameter called reader. When you’re writing the function, you know what Reader offers, so it’s not such a problem to not get code completion. And if you blank out on something, just keep zig std open on your second monitor.
That’s why I support that allocator arguments be changed to anytype, and the same applies to the future Io.

User-friendly or not, I highly recommend embracing the Reader interface, even when it was a type erasure. I wrote a reader that read files asynchronously and played nicely with my stackful coroutines implementation. With just that, I automatically got a reader that decompressed a zip file (zig standard library) and parsed the medical images on it (I had written it previously) while nicely yielding to allow for optimal IO. The code of the medical image parser was written with eyes on just reading the entire file into a buffer, and taking slices from it, like you mentioned. But I had to change strategies, and everything just worked, without touching the code.

4 Likes

I think devirtualization could be less of a myth, but it would take semantic changes to the language. If the type system could express that a table of function pointers was static, that would open up some possibilities currently closed off. Seems to be some of what #23367 is about, although that isn’t the only possible approach.

I agree about using anytype for readers and writers. In addition to getting compile-time monomorphization, it’s no different from using the AnyReader type in the event that the code only calls AnyReader, and leaves unlimited opportunities for new reader structs, which only have to fulfill the part of the interface which is actually used by the caller.

There’s an actual tooling problem here. Taking the long view, tolerating problems which can be fixed with tooling is the right decision, so I don’t mind it. But the lack of help which kicks in for passed-in type and anytype does impose friction for using genericity, which isn’t good.

I suggested type hints for ZLS as a sort of brute-force solution, and brute force or not, I think it would help.

That would allow completions to work as normal, hovers would show a sensible default, perhaps even a special syntax for type hints (¿T is actually not terrible: it’s obviously not a “real” type and can probably be parsed at a glance as “this type might not be true, depending”).

A way to tell the language server “yes this can be literally anything, but you can treat it as T for language serving purposes” would fit the vast majority of comptime duck-typing, and the type hint comment would not be without use to a reader of the code, either.

6 Likes