## digitalmars.D - Re: integer division with float result

Bruce Adams <tortoise_74 yeah.who.co.uk> writes:
```0ffh Wrote:

Here's another (non-D?) thought. How about overloading on the return
type? In a strongly typed language its only convention that makes the
return type somehow special. I believe the original reason for return
values being special may have been that they are the only things left on
the stack when returning from a function call. This was only true early
on when all arguments were passed by value. We don't seem to have moved
beyond that, we only tease around the edges with covariant returns and
returning multiple values but semantically there's no difference
between: [...] So why do we still insist on it in modern languages?

Regards,

Bruce.

Return type overloading is not practical, or at least not without solving a
few problems first. What return type would you expect from the function?
Okay, in an assignment it's clear.
What about function calls in expressions?
What if you have overloaded foo to return int or float, and bar to return
int or float. Then go and call bar(foo())... oooopsie! =)
And it's not always as easy as just int or float; think arbitrary types!
Okay, there are solutions to all this, but the only reasonable ones I
know need extra hints for the compiler (some kind of syntax extension,
or building a new semantic upon an available syntax).

Regards, Frank

I suspect what is required is type inference a la ML.
So in the case of
(in the following feel free to replace X with divde, Y with print and R with
random if that makes it easier to read).

int X(int a)
long X(long b)

void Y(int y)
void Y(long y)

void Z(int y)
void Q(long y)

int a = 1;
long b = 2;

Z(X(a)) is legal (no ambiguity)
Q(X(b)) is legal (no ambiguity)

Y(X(a))  - infer use of Y(int) because X(int) because a = int
Y(X(b)) - infer use of Y(long) because X(long) because b = long

The only place you have real ambiguity is:

int R(void)
long R(void)

so X(R()) is ambiguous and should thus cause a compile error.
It must be replaced with either:

int temp = R();
X(temp)

or X(cast(int)R())

This is trivial to implement in a compiler the type inference is a little more
tricky (though Walter did say he was interested in adding functional
programming features to D ;-).

I think a good syntactic sugar to use for that would be named parameters, which
are useful for so many other reasons (but much less trivial to implement)
So

Y(int Int)
Y(long Long)

would allow

X(Y(Int))

unfortunately this doesn't solve the problem for R because the return type
cannot be named
So casting cannot be eliminated entirely that way but it can be significantly
reduced. That's got to be a good thing surely?

Regards,

Bruce.
```
Nov 18 2007
0ffh <frank frankhirsch.youknow.what.todo.net> writes:
```Bruce Adams wrote:
So casting cannot be eliminated entirely that way but it can be
significantly reduced. That's got to be a good thing surely?

Well, the use of a cast as hint for the compiler looks like a
rather nice choice. But then I don't quite see how it improves
the thing about integer and float division apart from the case
of assignments. Take:

void foo(int);
void foo(float);

As it is now, I have for example

int i,j;
float f;
[...]
i=i/j; // implicit int
f=cast(float)i/j; // explicit float
foo(i/j); // implicit int
foo(cast(float)i/j); // explicit float

int i,j;
float f;
[...]
i=i/j; // implicit int
f=i/j; // implicit float
foo(i/j); // compiler error: under-determined type information
foo(cast(int)i/j); // explicit int
foo(cast(float)i/j); // explicit float

So now there are just different cases where a cast is needed.
For some people I am sure the case with overloaded return types
has more appeal, but for others it is different. It's just a
matter of tastes, really, as the C way is no more complicated
than the other way. It is just not what many people expect at
first. I can't yet see how this small improvement is worth the
trouble implementing.

Regards, frank
```
Nov 18 2007
0ffh <frank frankhirsch.youknow.what.todo.net> writes:
```0ffh wrote:
[...]
foo(cast(int)i/j); // explicit int
foo(cast(float)i/j); // explicit float

Oops; this is with syntactic sugar, BTW, as I was
just casting the first operand, not the expression.
Otherwise
foo(cast(int)(i/j)); // explicit int
foo(cast(float)(i/j)); // explicit float

(The current style example should work as it is.)

Regards, Frank
```
Nov 18 2007
Bruce Adams <tortoise_74 yeah.who.co.uk> writes:
```0ffh Wrote:

So casting cannot be eliminated entirely that way but it can be
significantly reduced. That's got to be a good thing surely?

Well, the use of a cast as hint for the compiler looks like a
rather nice choice. But then I don't quite see how it improves
the thing about integer and float division apart from the case
of assignments. Take:

void foo(int);
void foo(float);

As it is now, I have for example

int i,j;
float f;
[...]
i=i/j; // implicit int
f=cast(float)i/j; // explicit float
foo(i/j); // implicit int
foo(cast(float)i/j); // explicit float

int i,j;
float f;
[...]
i=i/j; // implicit int
f=i/j; // implicit float
foo(i/j); // compiler error: under-determined type information
foo(cast(int)i/j); // explicit int
foo(cast(float)i/j); // explicit float

So now there are just different cases where a cast is needed.
For some people I am sure the case with overloaded return types
has more appeal, but for others it is different. It's just a
matter of tastes, really, as the C way is no more complicated
than the other way. It is just not what many people expect at
first. I can't yet see how this small improvement is worth the
trouble implementing.

Regards, frank

Well I wasn't advocating a change to D (yet). Hence the non D in my original
post. It was more a thought experiment. Your use case above is certainly a
compelling reason not to do it this way, at least for division. I wonder if
there is not a way of having the best of both worlds. Still, I begin to see why
others want a seperate div operator. I shall ponder some more...
```
Nov 18 2007
0ffh <frank frankhirsch.youknow.what.todo.net> writes:
```Bruce Adams wrote:
0ffh Wrote:

int i,j; float f; [...] i=i/j; // implicit int f=i/j; // implicit
float foo(i/j); // compiler error: under-determined type information
foo(cast(int)i/j); // explicit  int
foo(cast(float)i/j); // explicit float
[...btw. thunderbird rewrapping does strange things to those lines...]

Well I wasn't advocating a change to D (yet). Hence the non D in my
original post. It was more a thought experiment. Your use case above is
certainly a compelling reason not to do it this way, at least for
division. I wonder if there is not a way of having the best of both
worlds. Still, I begin to see why others want a seperate div operator.
I shall ponder some more...

Far be it from me to add to the plethora of D feature requests, but
one possible solution might be giving an explicit precedence hierarchy
to the compiler at one point, e.g.

void foo(int){...}
void foo(float){...}
precedence foo(float) > foo(int);

could in case of ambiguity choose float over int.
But I'm not quite sure this could not backfire in some way...

Regards, frank
```
Nov 18 2007
0ffh <frank frankhirsch.youknow.what.todo.net> writes:
```0ffh wrote:
precedence foo(float) > foo(int);

Nah, that's bull shite.
We were talking return type overloading, so make that

precedence float opDiv(int,int) > int opDiv(int,int);

Good thing is, in my code I could adhere to the classic way. =)

regards, frank (sleepy)
```
Nov 18 2007