On Monday, April 30, 2018 21:11:07 Gerald via Digitalmars-d wrote: > I'll freely admit I haven't put a ton of thought into this post > (never a good start), however I'm genuinely curious what people's > feeling are with regards to the auto keyword. > > Speaking for myself, I dislike the auto keyword. Some of this is > because I have a preference for static languages and I find auto > adds ambiguity with little benefit. Additionally, I find it > annoying that the phobos documentation relies heavily on auto > obscuring return types and making it a bit more difficult to > follow what is happening which gives me a bad taste for it. > > Having said, the thing that really started my thinking about this > was this post I made: > > https://forum.dlang.org/thread/fytefnejxqdgotjkp...@forum.dlang.org > > Where in order to declare a public variable for the RedBlackTree > lowerBound/upperBound methods I had to fall back on using the > ReturnType template to declare a variable. Jonathan was nice > enough to point me in the right direction and maybe there's a way > to do this without having to fall back on ReturnType. However > this made be wonder if reliance on auto could discourage API > writers from having sane return types. > > So I'm curious, what's the consensus on auto?
I think that the overall consensus is that it's great but that you do have to be careful about using it when it reduces clarity without adding other benefits. I remember when std.algorithm didn't use auto in any of its function signatures, because there was a bug in ddoc that made it so that functions that returned auto didn't show up in the docs. It was terrible. Seeing it would have scared off _way_ more people than any concerns over auto returns being confusing. You really, really, really don't want to know what many auto return types look like - especially if ranges are involved. You end up with templates wrapping templates, and seemingly simple stuff ends up looking ugly fast - e.g. until returns something like Until!("a == b", string, char). Having auto in the documentation is _must_ nicer. Really, auto return functions make things possible that would never be possible without it simply because the code would be too hard to read. In the cases where all you care about is what API a return type has and not what the return type is, auto is a true enabler. Voldemort types then take than a step further by removing the possibility of referring to the type by name and forcing you to go off of its API, which improves maintenance from the perspective of the person maintaining the function (because then they can change the return type as much as they like so long as its API is the same). But even without Voldemort types, auto return types simplify the information to remove all of that extra stuff that you don't care about the type. Of course, that can be taken too far and/or handled badly. The user of a function doesn't necessary have to care what the return type is, but they _do_ have to know enough to know what its API is. And that means that whenever a function returns auto, it needs to be clear in its documentation about what it's returning. If it's not, then obviously, the use auto becomes a problem. At least an explicit return type would have then made it possible for the user to look up the return type, whereas with auto and bad documentation, they're forced to use stuff like typeof and pragma(msg, ...) to figure out what the type is or to go look at the source code. So, while auto is awesome, anyone writing such a function needs to do a good job with documentation and try to put themselves in the shoes of whoever is using the function. Another thing that can be taken from that is that if a function is designed to return something specific as opposed to an arbitrary type with a specific API, then it's generally better to put the type in the signature so that it's clear rather than use auto. As for auto inside functions, I'd argue that it should be used heavily, and I think that most of us do. The cases where there's really no debate are functions that return auto, and when using the type's name would just be duplicating information. e.g. it's just bad practice to do Type foo = new Type(42); instead of auto foo = new Type(42); Avoiding auto buys you nothing and just increases your code maintenance if you change the type later. It's when you start using auto all over the place that it gets more debatable. e.g. auto foo = someFunc(); foo.doSomething(); auto bar = someOtherFunc(foo); Depending on what the codes doing, heavy use of auto can sometimes make such functions hard to read, and some common sense should be used. However, by using auto, you're frequently making it easier to refactor code when types change, as they sometimes do. In that snippet, so long as I can call doSomething on foo (be it as a member function or via UFCS) and so long as someOtherFunc accepts whatever type foo is, I don't necessarily care if the type of foo changes. If I need to refactor someFunc so that it returns something else that has a compatible API, then someFunc can be changed without having to change the code using it, whereas if the type name had been used explicitly, I would have had to change a lot more. And if the new type doesn't have a compatible API, then it will fail to compile either way, so the use of auto didn't matter. The only real problem here is how readable the code is with auto, and that's going to be very dependent on what the code is doing it and who is reading it. But the types can still be figured out just by looking at the functions being called (and if you're actually using an IDE like many us don't, then you could probably hover your mouse over the type too see what it is without even looking at the documentation for the function), and honestly, I would argue that if you don't know what the functions being called are doing, then you need to look them up anyway. And if you do know what they're doing, then you know what they're returning, and auto isn't a problem at all. Really, if it becomes a readability problem, then use explicit types, but in general, I think that using auto ultimately makes the code more maintainable, much as it can take some getting used to. And I think that the biggest problems with using auto simply come from not being used to it and not knowing how to deal with it in those annoying cases where you need an explicit type but don't have one (e.g. to declare a member variable which isn't directly initialized) - but even that is really more of an issue with Voldemort types than auto specifically (much as they're related). I think that experienced D programmers tend to use auto pretty much everywhere inside of functions and only use explicit types where necessary. The bigger question is when to return auto or not, and as long as the documentation is solid, that's usually not a problem - though if using auto isn't going to buy you anything there, then you might as well make the type explicit, since that improves clarity and simplifies the documentation. - Jonathan M Davis