One thing that really annoyed me about D is that its documentation lists basically every function with an 'auto' return type. Auto should be completely banned from documentation, it's a complete hindrance. It's the single biggest contributor to why I stopped using D for personal projects - I was so tired of having to hunt down what functions are going to return, sometimes having to resort to just using it and looking at what the compiler complains about.And that's a huge shame. Because in general I really liked using D.
gmueckl|5 years ago
I am not sure what to make of this pattern. At least the documentation should be more explicit about these Voldemort types. Documentation has other issues as well. The standard documentation generator doesn't cope well with version statements (conditional compilation), potentially skipping docs for stuff that wouldn't be compiled into a particular build variant.
fluffything|5 years ago
The second one leaves me guessing what the return type is.
If the actual type cannot be named, it is rarely the case that this is all there is to it. Usually, users are expected to use that type "somehow" (it is a `Range`?), and that means that there are some interfaces that these types implement.
scott_s|5 years ago
edit: Looking at other answers, I think Range is probably not an interface like they exist in Java, but rather a pattern of behavior per templates in C++. Concepts are supposed to solve this problem in C++, but I don't know how well they actually do.
logicchains|5 years ago
With highly generic functions, it's often not possible to know what they'll return without knowing what you'll call them with. Especially given that D functions like "map" and "reduce" tend to return special iterator types so that the compiler is able to smarty fuse them where possible. If D had concepts like C++20, you could probably describe them with something looking like:
But at least for me that doesn't seem like it would be much more helpful than just reading the documentation, which states what the function returns, if not necessarily the type.rowanG077|5 years ago
asdkjh345fd|5 years ago
Of course it is. Map's type is "(a -> b) -> [a] -> [b]". D just absolutely and completely failed here, despite this being a solved problem 40 years ago.
WalterBright|5 years ago
slezyr|5 years ago
p0nce|5 years ago
Konohamaru|5 years ago
There is something so absurd about having "unnamed types" as an antipattern!
lumberjackstian|5 years ago
Another reason is the (ironically) dynamic nature of a return type. E.g.
auto whatDoesItReturn(int i)() { static if (i == 0) { return int.init; } else { return string.init; } }
Template code can do that quite easily and then you don't have a choice but to write auto as the return value.
What would be fantastic if the documentation could be given access to the the compiler's return type inference, so that it could document the auto returns with a little more info.
Another way useful approach would be to implement protocols like in swift, or traits like in scala/rust/others, signatures in ml, etc. Then you would be able to define the interface of what a function returns.
lultimouomo|5 years ago
I agree with your point, but for the sake of the audience who doesn't know D I think this example is misleading, as one could take the "int i" parameter as a runtime one, while it's actually a compile time one (the equivalent of C++ non-type template parameter). If you instantiate the function with 0 as a compile-time parameter, it is a function that returns int; otherwise it's a function that returns string. It is never a function that can return int or string.
schveiguy|5 years ago
I still think the best option is let the author describe it in ddoc, as the semantic meaning can be much easier to convey that way.
GordonS|5 years ago
If the docs are filled with this, then D is certainly coming off my list of langs to look at.
For functions that can return different types, I think interfaces or union types would be more helpful (not sure if D supports either though).
RandallBrown|5 years ago
skocznymroczny|5 years ago
Most people will tell you, "oh just use auto, it makes the code more generic". That's sweet, except as soon as I want to pass it to another function, I need to have the concrete type. Like you, I usually just copy-paste the full type from the error message and move on.
hibbelig|5 years ago
But if the body of the loop just refers to `x.getKey()` and `x.getValue()`, without extracting them into local variables, then it makes sense to put the exact `Map.Entry` type into the loop header.
stcredzero|5 years ago
It's 2020. Why couldn't things work like this, where one can open a window for a concrete type using templates, and it shows the code?
Pxtl|5 years ago
hiq|5 years ago
Of course good tooling is still a big requirement, but I still think it's the best decision in the long-term: it's way easier to improve and change tools like IDEs (especially with LSP?), rather than the language itself.
Regarding explicit types in functions, you also don't always need them in languages such as OCaml. I feel that the answer to your criticism could be to just have "auto" also for function arguments, especially when you're just prototyping.
acehreli|5 years ago
WalterBright|5 years ago
bachmeier|5 years ago
anaphor|5 years ago
self_awareness|5 years ago
Could you please paste some example of a function that has a return value which is declared as auto?
bachmeier|5 years ago
https://dlang.org/phobos/std_algorithm_sorting.html#partitio...
The important line is
auto pieces = partition3(a, 4);
So, what's the type of pieces? The D standard library is written to be generic. And sure enough, that line of code will run. Where it turns into a problem is when you try to do something with it. If pieces is a range, there are certain things you can't do with it. Or maybe you can. Who knows. You'll never learn it from reading the documentation. I've been using D since 2013 and I still struggle with this at times. It's a valid complaint. (D's a great language, but is short on manpower to fix rough edges like this.)
F-0X|5 years ago
In this (and the sibling pages in algorithm) nearly every entry is listed as either "template" or "auto" relhttps://dlang.org/phobos/std_algorithm_iteration.html
masklinn|5 years ago
takeda|5 years ago
schveiguy|5 years ago
But sometimes auto is the best tool for the job, especially when writing wrapping types. In that case, yes, you have to read the documentation (and I mean what is written in the ddoc comments). But in many cases, you don't have to, because you recognize the pattern, or it's simply a wrap of the underlying type's function.
dirtydroog|5 years ago
Koshkin|5 years ago
pansa2|5 years ago
logicchains|5 years ago
arunc|5 years ago
takeda|5 years ago
At least that's what I understood.
jbverschoor|5 years ago
lostmsu|5 years ago
jimbob45|5 years ago
Anyways, var/auto is critical in some cases. C#'s LINQ, for example, would be very difficult to develop with if you had to manually figure out the type you were returning with long queries every time you wanted to restructure your query.
ynx|5 years ago
TwoBit|5 years ago
JoeAltmaier|5 years ago
I wonder if the document could describe (in some regular way) how those auto types are constructed...from what input, with what operations?
WalterBright|5 years ago
z3t4|5 years ago
underthensun|5 years ago
ahartmetz|5 years ago
MaxBarraclough|5 years ago
(I see my snarky comment there got no reply.)
https://softwareengineering.stackexchange.com/a/180616/
stevefan1999|5 years ago
throwaway894345|5 years ago
In general, this reduces to the principle that concrete is easier to reason about than abstract. The type signature of an unannotated function in a type inference system is maximally abstract, while (especially in practice) the signatures for functions that are manually annotated are more concrete if not fully concrete. There are still problems in non-type-inferred systems with programmers who try to be egregiously abstract, but these are fewer and farther between.
Koshkin|5 years ago