November 15, 2012
On Thursday, 15 November 2012 at 17:18:04 UTC, Rob T wrote:
> I've been wondering for a couple of years about why overloading stops at the argument sig ...
>
> [SNIP]
>
> --rt

I'd say because overall, you gain *very* little out of it, and it costs you much more complex compiler rules.

Most of all though, I'd say it is a bad idea in and out of itself: If you overload on the return type, you open the floodgates to call ambiguity.

I mean, are there even any real use-cases for overload on return type?
November 15, 2012
monarch_dodra:

> I mean, are there even any real use-cases for overload on return type?

In Haskell many functions are "overloaded" on the return type (like the fromString function), and it's nice. But Haskell is able to do it because it has a global type inferencer.

Bye,
bearophile
November 15, 2012
Am 14.11.2012 20:07, schrieb Timon Gehr:
> On 11/14/2012 06:30 PM, Rob T wrote:
>> On Wednesday, 14 November 2012 at 09:16:13 UTC, Walter Bright wrote:
>>>> I'm not requesting this to be a feature of D, I'm only asking why it
>>>> is not
>>>> being done.
>>>
>>> Because types are resolved bottom-up, and if the return type were part of the overloading, there would be no sensible rule to determine the types.
>>
>> But doesn't the compiler already have to perform overload-like decision making on return types in the "alias this" case, esp once multiple conversions are allowed?
>>
>> class A{
>>    int i;
>>    bool b;
>>    alias i this;
>>    alias b this;
>> }
>>
>> main()
>> {
>>    auto a = new A;
>>    int i = a;
>>    bool b = a;
>> }
>>
>> --rt
> 
> alias this is not the best example, but the necessary logic is basically already in the compiler. Lambda parameter type deduction based on the expected type is a similar task.
> 
> It is not being done because it is not being done. Full type inference would be even more fun.

In the lambda case it's return type deduction and not overload resolution. Those are actually two very different things.
November 15, 2012
On Thursday, 15 November 2012 at 17:33:24 UTC, monarch_dodra wrote:
> I'd say because overall, you gain *very* little out of it, and it costs you much more complex compiler rules.
>

But how little, and for how much extra cost? Overloading already has a cost to it, and it's really difficult for me to understand why adding return type to the mix has to be be many times more costly. I will confess that I'm not a compiler designer, but I can still try to imagine what would be needed. Already the compiler MUST ensure that the return type is valid, so we're essentially already there from what I can see.

> Most of all though, I'd say it is a bad idea in and out of itself: If you overload on the return type, you open the floodgates to call ambiguity.

Sure, but not much more so that we have already with the current overloading system, and the compiler can certainly prevent an invalid compile from happening when there is even a hint of ambiguity, as it does already with current overloading. Besides I would expect such a feature to be used by advanced programmers who know what they are doing because overloading in general is an advanced feature and it is certainly not for the easily confused.

> I mean, are there even any real use-cases for overload on return type?

Yes, I've wanted this for a few years, and I have used a similar feature successfully through C++ class operator conversions.

I brought up the example of operator conversion for classes in C++. I know some of you have said it's not the same thing, but IMO it is the same thing.

int x = a;
string y = a;

Does "a" represent a class or a function? Why should it matter?

class A
{
   int i;
   string s;
   alias i this;
   alias s this; // ouch D does not allow it!
   ...
}

UFCS

int convert( A a )
{
   return a.i;
}

string convert( A a )
{
   return a.s;
}

int i = a.convert;
string s = a.convert;

A real-world use case example is to implement Variant types more naturally, where you could do the above and have it convert to int or string (and other types) on demand depending on the validity of data type. Obviously it will run-time error when the type cannot be converted, or perform whatever logic the programmer desires.

--rt

November 15, 2012
On 11/15/2012 07:09 PM, Sönke Ludwig wrote:
> Am 14.11.2012 20:07, schrieb Timon Gehr:
>> On 11/14/2012 06:30 PM, Rob T wrote:
>>> On Wednesday, 14 November 2012 at 09:16:13 UTC, Walter Bright wrote:
>>>>> I'm not requesting this to be a feature of D, I'm only asking why it
>>>>> is not
>>>>> being done.
>>>>
>>>> Because types are resolved bottom-up, and if the return type were part
>>>> of the overloading, there would be no sensible rule to determine the
>>>> types.
>>>
>>> But doesn't the compiler already have to perform overload-like decision
>>> making on return types in the "alias this" case, esp once multiple
>>> conversions are allowed?
>>>
>>> class A{
>>>     int i;
>>>     bool b;
>>>     alias i this;
>>>     alias b this;
>>> }
>>>
>>> main()
>>> {
>>>     auto a = new A;
>>>     int i = a;
>>>     bool b = a;
>>> }
>>>
>>> --rt
>>
>> alias this is not the best example, but the necessary logic is basically already in the compiler.
>> Lambda parameter type deduction based on the expected type is a similar task.
>>
>> It is not being done because it is not being done. Full type inference would be even more fun.
>
> In the lambda case it's return type deduction and not overload resolution. Those are actually two
> very different things.
>

Yes, lambda _return_ type deduction is less related, but I have never claimed otherwise.

Another case that shows how a compiler must be able to take into account the left hand side of an assignment in order to type check the right hand side:

int foo(int);
double foo(int);

void main(){
    double function(int) fun = &foo;
}
November 16, 2012
On Thursday, November 15, 2012 17:18:43 foobar wrote:
> I thought that Haskell doesn't have function overloading (which simplifies this greatly)... Anyway, I mostly meant "standard" imperative/OO languages. Sorry for the confusion.

It has pattern matching (which typically results in several of the same function with slightly different arguments, but the overall types are still the same). I'm unaware of it having full-on function overloading. But I don't think that I've ever tried it.

- Jonathan M Davis
November 16, 2012
On Friday, 16 November 2012 at 01:02:59 UTC, Jonathan M Davis wrote:
> On Thursday, November 15, 2012 17:18:43 foobar wrote:
>> I thought that Haskell doesn't have function overloading (which
>> simplifies this greatly)... Anyway, I mostly meant "standard"
>> imperative/OO languages. Sorry for the confusion.
>
> It has pattern matching (which typically results in several of the same
> function with slightly different arguments, but the overall types are still the
> same). I'm unaware of it having full-on function overloading. But I don't
> think that I've ever tried it.
>
> - Jonathan M Davis

This article describes return type overloading in Haskell by way of a clear example. It concludes demonstrating a real-world implementation of the concept.

http://matthewmanela.com/blog/return-type-overloading-in-haskell/

I'm not well versed in Haskell (first look ever), so I'm not sure, but it does seem to look like true return type overloading.

I also read an article that described Perl's overloading on return type, but this is less like the overloading we've been talking about, and more like a function being able to inspect the call context to decide what type should be returned.

--rt

November 16, 2012
Am 15.11.2012 22:05, schrieb Timon Gehr:
> On 11/15/2012 07:09 PM, Sönke Ludwig wrote:
>> Am 14.11.2012 20:07, schrieb Timon Gehr:
>>> On 11/14/2012 06:30 PM, Rob T wrote:
>>>> On Wednesday, 14 November 2012 at 09:16:13 UTC, Walter Bright wrote:
>>>>>> I'm not requesting this to be a feature of D, I'm only asking why it
>>>>>> is not
>>>>>> being done.
>>>>>
>>>>> Because types are resolved bottom-up, and if the return type were part of the overloading, there would be no sensible rule to determine the types.
>>>>
>>>> But doesn't the compiler already have to perform overload-like decision making on return types in the "alias this" case, esp once multiple conversions are allowed?
>>>>
>>>> class A{
>>>>     int i;
>>>>     bool b;
>>>>     alias i this;
>>>>     alias b this;
>>>> }
>>>>
>>>> main()
>>>> {
>>>>     auto a = new A;
>>>>     int i = a;
>>>>     bool b = a;
>>>> }
>>>>
>>>> --rt
>>>
>>> alias this is not the best example, but the necessary logic is basically already in the compiler. Lambda parameter type deduction based on the expected type is a similar task.
>>>
>>> It is not being done because it is not being done. Full type inference would be even more fun.
>>
>> In the lambda case it's return type deduction and not overload resolution. Those are actually two very different things.
>>
> 
> Yes, lambda _return_ type deduction is less related, but I have never claimed otherwise.
> 
> Another case that shows how a compiler must be able to take into account the left hand side of an assignment in order to type check the right hand side:
> 
> int foo(int);
> double foo(int);
> 
> void main(){
>     double function(int) fun = &foo;
> }

The point I was trying to make is that taking the LHS into account is one thing (be it return type or parameter type deduction). But selecting the right overload in presence of implicit type conversions is much more than that and brings a lot of problems. In particular I suspect that a solution could either be to flag every possible ambiguity as an error and thus possibly make resulting APIs badly usable, or to define resolution rules to at least handle some ambiguities but in turn make it difficult and non-obvious for the programmer what happens.

There can also be hidden ambiguities with number literals or custom operator overloads, things that are solvable but all add up.

But then again I don't really have concrete use cases that I can think of, so maybe in real cases it would not matter anyway and going with the always-error-out route would be fine.
1 2 3
Next ›   Last »