May 18, 2005
I think Walter has made it perfectly clear that he doesn't want return-type function overloading in D, but I'm curious about it.

I'm posting because I'd like to modify TinyCC's [http://tinycc.org/] source code to allow for return-type function overloading in the C language and play around with it.

What I'd like to know is what types of pitfalls and gotchas are likely to be introduced to the compiler writer by allowing overloading based on function return type, especially in type casting and type promotion rules.  Are there any ambiguities that can be tackled easily?  Any signficantly difficult challenges involved?  Is it completely impossible to achieve with the current language design of C and its type system?

I'd really like to theoretically explore the area with you guys before I try to design it in and get frustrated and give up =P.  Note I haven't given the problem entirely much thought - just want to spark some interesting discussion.

Regards,
James Dunne
May 18, 2005
James Dunne wrote:
> I think Walter has made it perfectly clear that he doesn't want return-type
> function overloading in D, but I'm curious about it.
> 
> I'm posting because I'd like to modify TinyCC's [http://tinycc.org/] source code
> to allow for return-type function overloading in the C language and play around
> with it.
> 
> What I'd like to know is what types of pitfalls and gotchas are likely to be
> introduced to the compiler writer by allowing overloading based on function
> return type, especially in type casting and type promotion rules.  Are there any
> ambiguities that can be tackled easily?  Any signficantly difficult challenges
> involved?  Is it completely impossible to achieve with the current language
> design of C and its type system?
> 
> I'd really like to theoretically explore the area with you guys before I try to
> design it in and get frustrated and give up =P.  Note I haven't given the
> problem entirely much thought - just want to spark some interesting discussion.
> 
> Regards,
> James Dunne

I'm not expert on compilers, but here is an example where it won't work:

int hack()
{
    writef("int .." \n);
    return 1;
}

Object hack()
{
    writef("Object .." \n);
    return null;
}

int main()
{
    hack(); //which function?
    return 0;
}
May 18, 2005
On Wed, 18 May 2005 16:37:26 -0600, Hasan Aljudy <hasan.aljudy@gmail.com> wrote:
> James Dunne wrote:
>> I think Walter has made it perfectly clear that he doesn't want return-type
>> function overloading in D, but I'm curious about it.
>>  I'm posting because I'd like to modify TinyCC's [http://tinycc.org/] source code
>> to allow for return-type function overloading in the C language and play around
>> with it.
>>  What I'd like to know is what types of pitfalls and gotchas are likely to be
>> introduced to the compiler writer by allowing overloading based on function
>> return type, especially in type casting and type promotion rules.  Are there any
>> ambiguities that can be tackled easily?  Any signficantly difficult challenges
>> involved?  Is it completely impossible to achieve with the current language
>> design of C and its type system?
>>  I'd really like to theoretically explore the area with you guys before I try to
>> design it in and get frustrated and give up =P.  Note I haven't given the
>> problem entirely much thought - just want to spark some interesting discussion.
>>  Regards,
>> James Dunne
>
> I'm not expert on compilers, but here is an example where it won't work:
>
> int hack()
> {
>      writef("int .." \n);
>      return 1;
> }
>
> Object hack()
> {
>      writef("Object .." \n);
>      return null;
> }
>
> int main()
> {
>      hack(); //which function?
>      return 0;
> }

Indeed. Similarly...

printf("%x,%d",hack(),hack());

The basic problem being that there is no information supplied/implied to disambiguate the call. This is not unique to return-type overloading however, consider:

import std.stdio;

void foo(int a)   { writefln("int"); }
void foo(float a) { writefln("float"); }

int main()
{
  long a = 5;
  foo(a);
  return 0;
}

D cannot disambigute the call, it gives an error. (Not sure what C does).

A solution proposed in the past (by me and others - to which there was some dislike) is to:
1. Give an error for the above
2. Require the use of cast(type) to disambiguate (much the same way operator overloading is disambiguated).

eg.

cast(int)hack();    // calls int hack()
cast(Object)hack(); // calls Object hack()

The objections seemed (to me to be) mostly differences of definition/concept, i.e. the idea that cast's 'purpose' is to convert data, not disambiguate function calls, so shouldn't be used here where no 'conversion' is actually required.

The fact remains (in my opinion) that it is used to disambiguate function calls, eg. (using my example above):

  foo(cast(int)a);

Does the cast convert data? debatable, in reality it's simply looking at less of the data in this case, it's not changing the data itself (like it would/could from long to float).

Is conversion the reason the programmer put it there? debatable, the programmer simply wanted to call 'that' function with 'that' data. Cast/conversion just happens to be the only way to do that.

So, while return-type casting would not involve *any* conversion in *any* sense, if the programmers intent is to call 'that' function then it's use signals the same intent, IMHO.

Other solutions involved inventing a new syntax for 'selecting an overload'.

Regan
May 18, 2005
On Wed, 18 May 2005 16:37:26 -0600, Hasan Aljudy wrote:

> James Dunne wrote:
>> I think Walter has made it perfectly clear that he doesn't want return-type function overloading in D, but I'm curious about it.
>> 
>> I'm posting because I'd like to modify TinyCC's [http://tinycc.org/] source code to allow for return-type function overloading in the C language and play around with it.
>> 
>> What I'd like to know is what types of pitfalls and gotchas are likely to be introduced to the compiler writer by allowing overloading based on function return type, especially in type casting and type promotion rules.  Are there any ambiguities that can be tackled easily?  Any signficantly difficult challenges involved?  Is it completely impossible to achieve with the current language design of C and its type system?
>> 
>> I'd really like to theoretically explore the area with you guys before I try to design it in and get frustrated and give up =P.  Note I haven't given the problem entirely much thought - just want to spark some interesting discussion.
>> 
>> Regards,
>> James Dunne
> 
> I'm not expert on compilers, but here is an example where it won't work:
> 
> int hack()
> {
>      writef("int .." \n);
>      return 1;
> }
> 
> Object hack()
> {
>      writef("Object .." \n);
>      return null;
> }
> 
> int main()
> {
>      hack(); //which function?
>      return 0;
> }

The 'int' one, as 'int' is the default return type if no other can be determined.

And consider the even 'harder' example:

 int hack()
 {
      writef("int .." \n);
      return 1;
 }

 Object hack()
 {
      writef("Object .." \n);
      return null;
 }

 void Bar(int a)
 {
 }

 void Bar(Object a)
 {
 }

 int main()
 {
      Bar(hack()); //which function?
      return 0;
 }

---------
I still maintain that because you can't work it out from the context then assume 'int'. And if there is no matching signature using this assumption, then issue a message.

If you need to be specific, then code ...

    Bar(Object hack());

And a really hard one would be ...


 int hack()
 {
      writef("int .." \n);
      return 1;
 }

 real hack()
 {
      writef("real .." \n);
      return 1;
 }

 int main()
 {
    int y;
    y = cast(int)hack(); //which function are you casting?
    return 0;
 }
------------------


-- 
Derek
Melbourne, Australia
19/05/2005 9:09:13 AM
May 18, 2005
On Thu, 19 May 2005 09:17:47 +1000, Derek Parnell <derek@psych.ward> wrote:
>> int hack()
>> {
>>      writef("int .." \n);
>>      return 1;
>> }
>>
>> Object hack()
>> {
>>      writef("Object .." \n);
>>      return null;
>> }
>>
>> int main()
>> {
>>      hack(); //which function?
>>      return 0;
>> }
>
> The 'int' one, as 'int' is the default return type if no other can be
> determined.

My initial thought is that this is dangerous. What if the programmer is un-aware of one of the overloads?

> And consider the even 'harder' example:
>
>  int hack()
>  {
>       writef("int .." \n);
>       return 1;
>  }
> Object hack()
>  {
>       writef("Object .." \n);
>       return null;
>  }
>
>  void Bar(int a)
>  {
>  }
>
>  void Bar(Object a)
>  {
>  }
> int main()
>  {
>       Bar(hack()); //which function?
>       return 0;
>  }

Solution:
Bar(cast(Object)hack()); // Object hack() called, Bar called
Bar(cast(int)hack());    // int hack() called, Bar called

> ---------
> I still maintain that because you can't work it out from the context then
> assume 'int'. And if there is no matching signature using this assumption,
> then issue a message.
>
> If you need to be specific, then code ...
>
>     Bar(Object hack());

Similarly:
Bar(cast(Object)hack());

> And a really hard one would be ...
>
>
>  int hack()
>  {
>       writef("int .." \n);
>       return 1;
>  }
> real hack()
>  {
>       writef("real .." \n);
>       return 1;
>  }
> int main()
>  {
>     int y;
>     y = cast(int)hack(); //which function are you casting?
>     return 0;
>  }
> ------------------

This is a good point/question. Assuming, as it's all you've specified here, that you want the result to be an 'int' which function of these two:

  int hack();
  Object hack();

is likely to be the one to give you the desired result?

Assuming both versions of 'hack' are written to achieve the same purpose or goal (if not, ideally one should be renamed) then the answer is "int hack();" as it's the more 'specialised' version, it returns the type you want.

If you did actually mean to cast the address of an object to an int (or had no control over the name of the functions), you could write:

cast(int)cast(Object)hack();

IMO that's not too much of an ask given this desire/goal is rare/unlikely enough that ugly or verbose syntax is not a total pain in butt. It would mean that cast(type) used for overload selection would have to identify 'Object' above and not 'int' as the overload selection, so, it's a complicated feature that's for sure.

In the rare situation you were actually doing something odd (casting an object to an int above), a single cast(type) will give the incorrect results. The rest of the time it should give the desired result. Either way the initial error should show the programmer all the various overloads, allowing them to correctly indicate the desired choice.

My main point is, I think an error is required initially. No assumption should be made.

Regan

May 19, 2005
On Thu, 19 May 2005 11:34:42 +1200, Regan Heath wrote:


[snip]
>>
>> The 'int' one, as 'int' is the default return type if no other can be determined.
> 
> My initial thought is that this is dangerous. What if the programmer is un-aware of one of the overloads?
> 

[snip]

> My main point is, I think an error is required initially. No assumption should be made.

Yes, I suspect you are correct. It follows the D way - if something is ambiguous then complain. ;-)

-- 
Derek
Melbourne, Australia
19/05/2005 10:22:17 AM
May 19, 2005
"James Dunne" <james.jdunne@gmail.com> wrote in message news:d6geed$d6b$1@digitaldaemon.com...
>I think Walter has made it perfectly clear that he doesn't want return-type
> function overloading in D, but I'm curious about it.
>
> I'm posting because I'd like to modify TinyCC's [http://tinycc.org/]
> source code
> to allow for return-type function overloading in the C language and play
> around
> with it.
>
> What I'd like to know is what types of pitfalls and gotchas are likely to
> be
> introduced to the compiler writer by allowing overloading based on
> function
> return type, especially in type casting and type promotion rules.  Are
> there any
> ambiguities that can be tackled easily?  Any signficantly difficult
> challenges
> involved?  Is it completely impossible to achieve with the current
> language
> design of C and its type system?

It's probably not impossible to achieve since the expression tree is a ...
well... tree. The algorithm would start at the root (if the root type is
known) and leaves of the tree and start deducing types towards the middle
and if they meet in a unique set of overload choices then the expression is
allowed. Otherwise it is disallowed. And I bet it wouldn't be all that
inefficient. It wouldn't be compatible with today's overloading choices
since implicit casts will swing choices one way or another. For example
today the code
  int f(int x) {..}
  short f(short x) {..}
  int a;
  short b;
  a = f(b);
  b = f(a);
works fine. When you start overloading based on return value the choices are
ambiguous if you start overload resolution based on the inputs or the
outputs. So in "disallow anything non-unique" the code above wouldn't
compile. The cast tricks would sort it out, though:
  a = f(cast(int)b);
for example.

The problems probably aren't technical but philosophical. Should a C-like language do that? Would large programs written to use it be more or less buggy/confusing/hard-to-maintain? Would it replace buckets of template hackery? I don't know the answers there.


May 19, 2005
Regan Heath wrote:
> 
>> I'm not expert on compilers, but here is an example where it won't work:
>>
>> int hack()
>> {
>>      writef("int .." \n);
>>      return 1;
>> }
>>
>> Object hack()
>> {
>>      writef("Object .." \n);
>>      return null;
>> }
>>
>> int main()
>> {
>>      hack(); //which function?
>>      return 0;
>> }
> 
> 
> Indeed. Similarly...
> 
> printf("%x,%d",hack(),hack());
> 
> The basic problem being that there is no information supplied/implied to  disambiguate the call. This is not unique to return-type overloading  however, consider:
> 
> import std.stdio;
> 
> void foo(int a)   { writefln("int"); }
> void foo(float a) { writefln("float"); }
> 
> int main()
> {
>   long a = 5;
>   foo(a);
>   return 0;
> }
> 
> D cannot disambigute the call, it gives an error. (Not sure what C does).
> 
> A solution proposed in the past (by me and others - to which there was  some dislike) is to:
> 1. Give an error for the above
> 2. Require the use of cast(type) to disambiguate (much the same way  operator overloading is disambiguated).
> 
> eg.
> 
> cast(int)hack();    // calls int hack()
> cast(Object)hack(); // calls Object hack()

The problem with that is, you need to have the object /before/ you make the cast.
The way I understand cst is: "take this chunck of memory, reinterpret it (or decode it) as if it was of this type", where "this type" is what you want to cast to.
If you can't retrive the data, how are you going to cast it?

> 
> The objections seemed (to me to be) mostly differences of  definition/concept, i.e. the idea that cast's 'purpose' is to convert  data, not disambiguate function calls, so shouldn't be used here where no  'conversion' is actually required.
> 
> The fact remains (in my opinion) that it is used to disambiguate function  calls, eg. (using my example above):
> 
>   foo(cast(int)a);
> 
> Does the cast convert data? debatable, in reality it's simply looking at  less of the data in this case, it's not changing the data itself (like it  would/could from long to float).

something like
foo(5);
is a call that passes constants. Now, literal constants are part of the language, and the type of a constant is determined by the language.

I think in C, 5 is an int, while 5.0 is a double.
I don't know what D does with that.

But when you
cast(int)5
you are not removing ambiguity, you are writing an expression that returns an "int".
The data is already vilable, it's 5, and when you cast it to an int, you 
 are essentially removing an ambiguity, but actually you are just writing an expression that returns a known type (hence no ambiguity).

> 
> Is conversion the reason the programmer put it there? debatable, the  programmer simply wanted to call 'that' function with 'that' data.  Cast/conversion just happens to be the only way to do that.
> 
> So, while return-type casting would not involve *any* conversion in *any*  sense, if the programmers intent is to call 'that' function then it's use  signals the same intent, IMHO.
> 
> Other solutions involved inventing a new syntax for 'selecting an  overload'.
> 
> Regan

A better way maybe to introduce a new concept, that is, a new keyword, so instead of cast(type), we may say call(type) or something like that.

But it would not be a "cast".
May 19, 2005
On Wed, 18 May 2005 19:33:13 -0600, Hasan Aljudy wrote:


[snip]

> A better way maybe to introduce a new concept, that is, a new keyword, so instead of cast(type), we may say call(type) or something like that.
> 
> But it would not be a "cast".

I'm a bit wary of reusing 'cast' for this purpose too. A new keyword would be a better alternative.

-- 
Derek
Melbourne, Australia
19/05/2005 11:37:17 AM
May 19, 2005
"Hasan Aljudy" <hasan.aljudy@gmail.com> wrote in message news:d6gg2v$eb7$1@digitaldaemon.com...
> James Dunne wrote:
> > I think Walter has made it perfectly clear that he doesn't want return-type function overloading in D, but I'm curious about it.
> >
> > I'm posting because I'd like to modify TinyCC's [http://tinycc.org/] source code to allow for return-type function overloading in the C language and play around with it.
> >
> > What I'd like to know is what types of pitfalls and gotchas are likely to be introduced to the compiler writer by allowing overloading based on function return type, especially in type casting and type promotion rules.  Are there any ambiguities that can be tackled easily?  Any signficantly difficult challenges involved?  Is it completely impossible to achieve with the current language design of C and its type system?
> >
> > I'd really like to theoretically explore the area with you guys before I try to design it in and get frustrated and give up =P.  Note I haven't given the problem entirely much thought - just want to spark some interesting discussion.
> >
> > Regards,
> > James Dunne
>
> I'm not expert on compilers, but here is an example where it won't work:
>
*snip*
>

Okay, here's a thought.  What it instead of complete overriding based on return type, it were made possible to
include code in a function that would return more than once type, and any return statement that returns
an incompatible type would simply be skipped over.  In the case where no return value is made use of,
there would be no such thing as an incompatible return value, so the first return would encountered would be accepted.

autotype hack()
{
     writef("testing..." \n);
     return 1;
     writef("not int .." \n);
     return 'a';
     writef("not char .." \n);
    return null;
}

int main()
{
     char b;
     b = hack(); // returns 'a' which is assigned to b.
     hack(); // returns 1, which is discarded anyway.
     return 0;
}

This way, the function could be called as any type that it is capable of returning.

Obviously, not as versitile.. but quite possibly also not as troublesome.  A good compromise, perhaps?

Another interesting possibility would be to expose the requested return type of a function from within that function...

autotype hack()
{
     if (this.typeof == ...

TZ


« First   ‹ Prev
1 2 3 4 5 6 7 8
Top | Discussion index | About this forum | D home