literals
Fawzi Mohamed
fawzi at gmx.ch
Sun Mar 28 15:13:38 PDT 2010
On 28-mar-10, at 22:34, so wrote:
> On Mon, 29 Mar 2010 00:46:20 +0400, Don <nospam at nospam.com> wrote:
>
>> so wrote:
>>> Hello Don, finally!
>>> It is hard to explain yourself when you don't know the people you
>>> talk have numeric coding background.
>>> Since we know you have done much numeric and generic coding, it
>>> will be enough for me if you understand what i mean/ask/want,
>>> and say what i am talking is ridiculous, or think that i am
>>> trolling, just say so and i shut up! :)
>>
>> You're definitely not trolling! I'm not 100% sure of which issue
>> you're referring too, but I'm aware of a few, for example:
>>
>> (1) Converting a floating point literal into a double literal is
>> usually not lossless.
>> 0.5f, 0.5, and 0.5L are all exactly the same number, since they are
>> exactly representable.
>> But 0.1 is not the same as 0.1L.
>> So it's a bit odd that this silent lossless conversion is taking
>> place.
>> It does have a very strong precedent from C, however.
>>
>> (2) The interaction between implicit casting and template
>> parameters is quite poor. Eg, the fact that '0' is an int, not a
>> floating point type, means that something simple like:
>> add(T)(T x) if (isFloatingPoint!(T))
>> doesn't work properly. It is not the same as:
>> add(real x)
>> since it won't allow add(0).
>>
>> Which is pretty annoying. Why can't 0 just mean zero???
>
> At the beginning the question in my mind was, why can't we do this
> the way it works in math :
>
> [Real numbers] contains [Integers] contains [Natural numbers]
>
> So, when a compiler see 0, which is the element of all above, it
> should classify it as :
> 1st degree. [floating point type, integer, natural number]
> When it encounters say, -3, it will be :
> 2nd degree. [floating point type and integer]
> And finally when it encounters something like 4.0, it will be :
> 3rd degree. [floating point type]
>
> With these in mind, the prototype :
>
> T foo(T)(T m) {}, should be able to take all three degrees of types
> above.
>
> We go abit further and see what it actually is :
>
> T foo(T)(T m) {
> T n = m * 5 - 4 * 7 / 2; // numbers belongs all the systems above,
> this line should work for every T
> T k = n / 20; // same.
> return n + k; // same.
> }
>
> "T n = m * 5 - 4 * 7 / 2;"
> m is here in the type of T,
> * operator has a generic operand 5, convert it to T, if you can't,
> pop error.
> - operator has a generic operand (4 * 7 / 2), expect it in the and
> keep parsing.
>
> Again, in the code above, none of the constants is a native type, as
> in 5 is not int, it is a generic constant which belongs all systems
> above.
> What this means?
>
> calling foo(0.0f) is actually :
> float foo(float m) {
> float n = m * 5.0f - 4.0f * 7.0f / 2.0f;
> float k = n / 20.0f;
> return n + k;
> }
>
> m is here float and operation * has a generic operand
>
> There wasn't a single implicit cast and the code was perfectly
> generic.
why do you see implicit cast as bad? for me the change from 5 to 5.0f
that you have above *is* an implicit cast, and is exactly what you want.
For 4 * 7 / 2, well that should either be calculated as integer or as
float, it is unlikely that both are correct.
Some languages decided to use a different symbol for integer division
and float division.
without that the thing is kind of ambiguous, and D chooses integer
division, and only later implicit conversion to float.
What I do agree with is that writing generic float literals is
cumbersome (using cast(T)x).
Implicit cast is what happens to stuff that can also be seen as a type
X so natural number -> integers,... implicit cast should not discard
precision, and should maintain the value, and is a *good* thing in
general (if the rules are sensible).
> calling foo(0) will pass the "if(isFloatingPoint!(T))" contract,
> since 0 belongs to all,
> but compiler will be unable to resolve the final type which is to be
> instantiated.
that gets easily very annoying, even aldor, that basically did all
what you wanted, and complained about unclear overload did an
exception for integers, so that they would default to Int....
Still I find D approach reasonable
More information about the Digitalmars-d
mailing list