literals
so
so at so.do
Sun Mar 28 13:34:56 PDT 2010
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.
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.
But coming with something like this would be suicide since i already got
enough treatment for the lighter syntax :P
Sorry for the long post!
Thanks.
--
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
More information about the Digitalmars-d
mailing list