EDIT: I see now that youāre trying to instantiate the struct in the function before you return it.
This could be solved in a few simple ways:
Just pre-declare the struct as a constant and instantiate it normally
Separate the struct declaration into a different Iterator() function that returns a type, and change the return type of the iterator() function to Iterator()
Donāt instantiate the struct in the function call, but instantiate it directly after calling the function like so: var iterator: Iterator() = .{};
I also think that itās annoying sometimes that you canāt do that. And sometimes itās really annoying to work around it because it can destroy code locality.
I assume that the function returns a constant because you simplified your example to make it easier for us. Anyway, this should work:
If you want your code to work just replace anytype with type.
anytype can be used only with functions parameters, to derive the type from the call site type.
You might want to derive a return type, and there are two different ways to do it.
Derive it from the return statement value type. This was proposed in the past and was rejected. The reason was mostly the bad experience from D programming language that have a similar concept.
Derive it from the use of the return value in the call site. This is a open issue that Iā ll love to have.
The whole point here is to avoid leaking the result type out of the iterator function. Yes, it is not a necessary feature. I just wonder if this is possible from tech view. If it is possible, is the reason why it is not supported is compilation speed related?
Even if it wasnāt accessible directly, somebody could just use @TypeOf(it) to get the type, so I am unsure what you want to achieve, is the intent to have less exposed declarations or something else?
Allowing this would lead to what D calls Voldemort types: types which one can use, but canāt āspeak its nameā.
var iter: ??? = iterator();
D considers this a good thing, Zig does not.
Thereās nothing to put in the ???, you couldnāt give it a name if you wanted to. This goes against Zigās values, which favor legibility: it should generally be possible to annotate the type of something, even if that gets weird (e.g. having an if statement mirrored on the LHS and RHS).
Also, an anytype return type would allow for completely duck typed Zig, everything could have the signature fn (anytype) anytype and just use tuple call syntax. I didnāt immediately spot the issue where anytype returns were decided against, but I remember these considerations being a factor in that decision.
I very occasionally am writing some reflection-heavy operation, and end up duplicating a big chunk of the function logic in a block which just provide the return type of the function. Itās a bit awkward, but itās rare, and itās ok if weird stuff looks weird, Iād say itās good actually.
If it means I never have to open up a file and discover that every function just says anytype for its return value, thatās a fair trade. Bad enough when all the error types are just left inferred, and thatās common; I wouldnāt want to see it spread to the return types themselves.
As many people have mentioned in this particular example you can fix it by replacing with ātypeā
However Iāll share something that can solve similar problems that have happened to me, many times I have functions that donāt know the type of the return value immediately.
In those cases a solution I found was to make a function just to calculate the type.
so instead of
functionOfUnknownReturnType(x: anytype) anytype {}
which zig doesnāt allowbb
You can have
functionOfUnknownReturnType(x: anytype) findType(x) {}
then a function
findType(x: anytype) type {}
inside the findType function you can calculate the type of the value the previous function would return.
Itās a bit tedious to write, and them might be some code duplication but when you come back to it later you at least have some information as to what the return type will be.
I still donāt really understand why. Of all the solutions here, this was one of the ones that was listed as being unreadable, and frankly I agree. I read the linked article about D and all the comments here, and I donāt really get the argument against just returning type from your function, or, if you for some weird reason really do want to hide the type, declaring the struct at the same level as the function, and if you want to expose functions that wrap your struct, you can mark them as pub and make sure those are the only functions in the file, treating it like a module. Again though I ask, why? The argument D gave about having to see the RandomNumberGenerator type all over doesnāt really apply in Zig, because you could name your function whatever you want, and you only need to write it on the right-hand side. Sure, itās in the namespace, but does that matter?
Isnāt this Voldemort then? That is sometimes how I feel it!
Somehow i tend to agree that it should be possible to return a anytype because it is possible for built-ins. Not fair
It does if you want the language to remain consistent, which of course is a decision for the language designer. The strong tendency I see is for Zig to be kept as consistent and simple as possible, and omit features that arenāt necessary and would add inconsistency, even if they might be convenient in some cases. If anything, I see that features are sometimes removed to make it simpler and more consistent.
Being able to refer to the result location type in any way, within the body of the function, and by reference in the result statement: Iāve wanted that a few times.
Itās kind of the anti-Voldemort though: you canāt use it at all if you canāt say what the type is. Doesnāt have to be an explicit annotation, Zigās result types are nicer than that, but itās passing certainty down rather than propagating uncertainty up. It would mean the caller can āduck typeā the result, not just the parameters.
The effect would be⦠not trivial though, since where does the result location type come from? Well the result type obviously. Except now weāre trying to work it in the other direction.
Iām doing fine without this, frankly. Sometimes Iāve wanted the result location itself, mainly out of paranoia that a struct is going to get copied off the stack instead of put straight into the result location as I would prefer. But I started doing the TigerBeetle thing of creating an undefined on the stack and constructing it by pointer, because thatās guaranteed to work, so I havenāt thought about it in awhile.