August 20, 2014
On Wednesday, 20 August 2014 at 16:45:49 UTC, ketmar via Digitalmars-d wrote:
> On Wed, 20 Aug 2014 16:34:40 +0000
> via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
>> No, the type of (cond ? x : 42) is always `int`, the `ref` already gets lost inside the ternary operator. So in this case, it behaves correctly.
> it's slightly counterintuitive. yes, this is correct, but D already
> complains on things like (a&b == c), so it can complain on such returns
> too -- just to avoid disambiguation. something like "use return
> cast(int)".

What would `cast(int)` do in this case? Note that `ref` is not part of the type -- it's a storage class associated only with the variable (= parameter).
August 20, 2014
On Tuesday, 19 August 2014 at 22:28:27 UTC, Peter Alexander wrote:
> Consider these two functions:
>
> auto ref foo(ref int x) {
>   if (condition) return x;
>   return 3;
> }
>
> auto ref bar(ref int x) {
>   return condition ? x : 3;
> }
>
> At a first glance, they appear to be equivalent, however foo is a compile-time error "constant 3 is not an lvalue" while bar compiles fine and returns an rvalue int.
>
> The  rule in the spec is "The lexically first ReturnStatement determines the ref-ness of [an auto ref] function"
>
> Why is this? I think it would be more consistent and convenient to be: "An auto ref function returns by ref if all return paths return an lvalue, else it returns by value".
>
> Am I missing something? I don't see why foo should be rejected at compile time when it can happily return by value.
>
> It is especially problematic in generic code where you opportunistically want to return by ref when possible, e.g.:
>
> auto ref f(alias g, alias h)()
> {
>   if (condition)
>     return g();
>   return h();
> }
>
> If g returns by ref while h returns by value then this fails to instantiate. It would be nice if it just returned by value (as return condition ? g() : h() would)

If I agree, you must understand that this increase wildly the cost of the analysis required to infer return type and/or refness.

It makes the compiler implementation *way* more complex and could increase the compilation cost a lot.

Consider that auto ref functions can happily call each others and you'll have to go through each of them as a graph, having set of possible return type and refness, aggregate these infos on a per function basis, removing cycles (so a function return type do not depend on itself).

This hack in the spec come handy, and, unless we can come up with a good implementation of a more general spec, I'd argue for it to stay there.
August 21, 2014
On Wed, 20 Aug 2014 18:24:29 +0000
via Digitalmars-d <digitalmars-d@puremagic.com> wrote:

> What would `cast(int)` do in this case?
just clarifying the intentions. remember that programs are written for humans in the first place, and programs should be easy to read for humans. it's not so hard to type extra nine chars, but the reader then knows what author really wants and sure that author not slipped in the crack of specs/specific realisation.

"(a&b == c)" is perfectly valid too, yet compiler rejects it, demanding clarification from the author.


August 21, 2014
On 08/20/14 23:39, deadalnix via Digitalmars-d wrote:
> On Tuesday, 19 August 2014 at 22:28:27 UTC, Peter Alexander wrote:
>> It is especially problematic in generic code where you opportunistically want to return by ref when possible, e.g.:
>>
>> auto ref f(alias g, alias h)()
>> {
>>   if (condition)
>>     return g();
>>   return h();
>> }
>>
>> If g returns by ref while h returns by value then this fails to instantiate. It would be nice if it just returned by value (as return condition ? g() : h() would)
> 
> If I agree, you must understand that this increase wildly the cost of the analysis required to infer return type and/or refness.
> 
> It makes the compiler implementation *way* more complex and could increase the compilation cost a lot.
> 
> Consider that auto ref functions can happily call each others and you'll have to go through each of them as a graph, having set of possible return type and refness, aggregate these infos on a per function basis, removing cycles (so a function return type do not depend on itself).
> 
> This hack in the spec come handy, and, unless we can come up with a good implementation of a more general spec, I'd argue for it to stay there.

While D's `ref` is a hack, it's /already/ part of the function type/signature.
The return type of a function is /already/ (ie in the D dialects supported
by recent frontend releases) determined from *all* returned expression.
What would be the advantage of propagating/inferring only the type, but not
the lvalueness?...

artur
August 21, 2014
On Thursday, 21 August 2014 at 05:24:13 UTC, Artur Skawina via Digitalmars-d wrote:
> While D's `ref` is a hack, it's /already/ part of the function type/signature.
> The return type of a function is /already/ (ie in the D dialects supported
> by recent frontend releases) determined from *all* returned expression.
> What would be the advantage of propagating/inferring only the type, but not
> the lvalueness?...

I think I understand the issue better now.

D doesn't always deduce a common return type, e.g.

class A {}
class B {}

auto foo() {
	return new A();
	return new B();
}

This fails to compile with "mismatched function return type", even though it could easily return Object. However, it seems to do some deduction of sorts with integral types, e.g. this deduces to return double.

auto foo() {
	return 0;
	return 0.0;
	return 0UL;
}

I'm not sure what logic it is using to do common type deductions. I haven't investigated fully.

The problem comes with recursion, which we don't handle at the moment for auto or auto ref functions, but handling that becomes much easier when you just assume the return type is the return type from the first return statement, so I see the value in the described approach.
1 2
Next ›   Last »