Thread overview
Using consistently auto as function return type
Jun 16, 2012
Tommi
Jun 16, 2012
Era Scarecrow
Jun 16, 2012
Timon Gehr
Jun 16, 2012
bearophile
June 16, 2012
Do you consider it to be good or bad style of programming to use consistently auto as function return type?

One of the pros is that it saves some redundant typing when the function returns some complex templated type:

auto getValue()
{
    return MyType!(int, "asdf", 64).init;
}

But one of the cons is that you don't see what the function returns just by looking at the signature.

Are there some more severe issues that I'm missing?
June 16, 2012
On Saturday, 16 June 2012 at 09:31:35 UTC, Tommi wrote:
> Do you consider it to be good or bad style of programming to use consistently auto as function return type?
>
> One of the pros is that it saves some redundant typing when the function returns some complex templated type:
>
> auto getValue()
> {
>     return MyType!(int, "asdf", 64).init;
> }
>
> But one of the cons is that you don't see what the function returns just by looking at the signature.
>
> Are there some more severe issues that I'm missing?

 I've wondered a bit of this myself. I tend to have all my function return types explicit and tend to use auto more for values returned when I am going to be using them right away, or they vary slightly on type (but not function).

 Being as D is not C++ (with it's template system), it can still parse and make sense of a majority of the code but lacking a specific return type... I want to say it's a potential pitfall and trap for later. If it only returns a basic type then the problem isn't as severe since implicit casting can take place to fix minor variations of type (real/double, int/long, etc).

 Perhaps a suggestion on use, where auto should be used: As a lambda return type, or functions that return simple base types?  Not to say it would prevent you from from using auto, but then the potential damage is lessened. Perhaps a bigger problem is that auto would hide type changes and potential problems because it was auto, but regarding templates with that I don't know. Mmmm... I need more experience.
June 16, 2012
On 06/16/2012 11:31 AM, Tommi wrote:
> Do you consider it to be good or bad style of programming to use
> consistently auto as function return type?
>
> One of the pros is that it saves some redundant typing when the function
> returns some complex templated type:
>
> auto getValue()
> {
>      return MyType!(int, "asdf", 64).init;
> }
>
> But one of the cons is that you don't see what the function returns just
> by looking at the signature.
>
> Are there some more severe issues that I'm missing?

auto return types make functions semantically dependent on each other,
eg. the following is illegal code:

auto foo(){bar(); return 0; }
auto bar(){foo(); return 1; }

In order to resolve the return type of foo, the body of foo needs to be
analyzed, which involves resolving the return type of bar, therefore
the body of bar needs to be analyzed, which involves resolving the
return type of foo, therefore the body of foo needs to be analyzed, ...


The current implementation is very conservative, and rejects every
dependency cycle of auto return functions, even if the return types
could be resolved in theory.


Other than that, there are no more severe issues, I see these major
applications for auto return types:

- The body is very short and spells out the type explicitly, auto saves redundancy.

- The implementer does not know the exact return type himself, because
  it depends on template arguments.

- The user of the function does not need to know the return type. eg if
  it is a type local to the function.
June 16, 2012
Tommi:

> Do you consider it to be good or bad style of programming to use consistently auto as function return type?

In Python programming you don't specify the types of function arguments and return values, but while this is possible in Haskell too, it's good practice to write down input and output types for functions, and let the type inferencer work just inside functions.

In D I use auto often inside function, unless I want to change a type or unless I want to be sure a certain variable has a desired type. But for clarity/readability I prefer to specify input/output types of D functions, unless they return a complex range. In this case I sometimes add a static assert to be sure it yields a range of my desired type:

auto foo(...)
out (result) {
    static assert(ForeachType!(typeof(result)) == ushort);
}
body {
...
}


Bye,
bearophile