Jump to page: 1 2
Thread overview
std.conv.to vs. casting
Jul 04, 2013
CJS
Jul 04, 2013
monarch_dodra
Jul 04, 2013
monarch_dodra
Jul 04, 2013
monarch_dodra
Jul 04, 2013
CJS
Jul 04, 2013
Ali Çehreli
Jul 04, 2013
Ali Çehreli
Jul 04, 2013
H. S. Teoh
Jul 04, 2013
monarch_dodra
July 04, 2013
I'm having trouble understanding the difference between casting and std.conv.to. Any help?
July 04, 2013
On Thursday, 4 July 2013 at 06:18:21 UTC, CJS wrote:
> I'm having trouble understanding the difference between casting and std.conv.to. Any help?

Casting merely changes the "observed type", whereas "to" does a deep conversion.

Observe:

----
import std.stdio;
import std.conv;

void main()
{
    int[] ints  = [1, 2, 3];
    auto bytes1 = cast(ubyte[])(ints);
    auto bytes2 = to!(ubyte[])(ints);
    writeln(bytes1);
    writeln(bytes2);
}
----
[1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0]
[1, 2, 3]
----

To is very useful to do "true" type conversion. It can change string width. Finally, "to" is able to do string interpretation. EG:

----
import std.stdio;
import std.conv;

void main()
{
    int[] ints  = to!(int[])("[1, 2, 3]");
    writeln(ints);
}
----
[1, 2, 3]
----

To is very convenient because it is a "one stop shop": It doesn't matter what you want to do: "to" will do it. You don't need to mix/match calls to atoi/itoa/encode/decode etc. Furthermore, it is safe: if anything fails, to will throw. It will also throw if you overflow:

----
import std.conv;

void main()
{
    int a = 500;
    ubyte b = cast(ubyte)(a); //No problem here: Silent overflow
    ubyte c = to!ubyte(a);    //Runtime overflow exception
}
----

Hope that helps :)
July 04, 2013
On 07/04/2013 10:14 AM, monarch_dodra wrote:
> Casting merely changes the "observed type", whereas "to" does a deep conversion.

What are the speed implications of to compared to cast?

I ask because I see various casts in Phobos, and wonder if there isn't improved safety in preferring instead to use to, so long as the optimal speed is there with appropriate compiler optimizations.

I'm particularly concerned here because of a bug I observed that would have been caught if to had been used rather than cast: http://d.puremagic.com/issues/show_bug.cgi?id=10322#c4

(I'm working on a fix, it's just time constraints that have delayed delivering it:-)
July 04, 2013
On Thursday, 4 July 2013 at 09:31:42 UTC, Joseph Rushton Wakeling wrote:
> On 07/04/2013 10:14 AM, monarch_dodra wrote:
>> Casting merely changes the "observed type", whereas "to" does a deep conversion.
>
> What are the speed implications of to compared to cast?
>
> I ask because I see various casts in Phobos, and wonder if there isn't improved
> safety in preferring instead to use to, so long as the optimal speed is there
> with appropriate compiler optimizations.
>
> I'm particularly concerned here because of a bug I observed that would have been
> caught if to had been used rather than cast:
> http://d.puremagic.com/issues/show_bug.cgi?id=10322#c4
>
> (I'm working on a fix, it's just time constraints that have delayed delivering it:-)

Speed implications, it mostly only means doing an "if (a > T.max)". It also means adding code to handle a throw. Finally, it means the function can't be marked nothrow.

I'd argue that "to" should really only be used for legitimate cases where the runtime can create out of range values, and you want to catch that as an exception. Speed should not be a real issue*.

I didn't go into the details, but in your bug report, it seems like it is more of an implementation error ? In that case, an ERROR would be better.

*Speed wise, it is not a problem I'd say, except maybe in range primitives, espcially empty, front and opIndex, and to a certain, popFront. It depends on the relative cost of the operation of course.

For example: Cycle provides RA indexing. the code is written as:
"return source[(currentIndex + inputIndex) % length];"

In this specific case, there is an overflow risk, even though RA access should be un-bounded. However, it is not checked, as the implications to calling to would be problematic. Placing an assert there is better, so release does not have to pay for the check.
July 04, 2013
On 07/04/2013 12:08 PM, monarch_dodra wrote:
> I didn't go into the details, but in your bug report, it seems like it is more of an implementation error ? In that case, an ERROR would be better.

The cast should be safe, as it's a size_t to a double.  It's just that having to!double() would have identified a problem, and if the speed hit would be avoided with the use of -release -noboundscheck I'd have assumed it would be worth it.

But you're right, the simplest thing to do is to fix the implementation error.

Related note -- what would you anticipate about the speed hit of isNan(x) versus
if(booleanValue) ... ?  Yes, I'll benchmark. :-P
July 04, 2013
On Thursday, 4 July 2013 at 10:15:22 UTC, Joseph Rushton Wakeling wrote:
> On 07/04/2013 12:08 PM, monarch_dodra wrote:
>> I didn't go into the details, but in your bug report, it seems like it is more
>> of an implementation error ? In that case, an ERROR would be better.
>
> The cast should be safe, as it's a size_t to a double.  It's just that having
> to!double() would have identified a problem, and if the speed hit would be
> avoided with the use of -release -noboundscheck I'd have assumed it would be
> worth it.
>
> But you're right, the simplest thing to do is to fix the implementation error.
>
> Related note -- what would you anticipate about the speed hit of isNan(x) versus
> if(booleanValue) ... ?  Yes, I'll benchmark. :-P

I'm trying to read the bug entry, but I don't get it. Maybe a reduced case to explain?

In any case, I don't think int to double ever throws so that wouldn't help...
July 04, 2013
On Thursday, 4 July 2013 at 10:23:22 UTC, monarch_dodra wrote:
> I'm trying to read the bug entry, but I don't get it. Maybe a reduced case to explain?

Point is, the skip() function in std.random.RandomSample can be called with the floating-point variable _Vprime equal to nan, _if_ popFront() or index() are called before front().

If isNan(_Vprime) && !_algorithmA then skip() will generate incorrect results.

I was asking about the speed of isNan compared to if(boolean) because I was considering killing the bool _first and just using isNan(_Vprime) to check if the first sample point has already been generated.

I can prepare a reduced example but it's probably simpler for me to just prepare a bugfix and do some benchmarks.
July 04, 2013
On Thursday, 4 July 2013 at 10:32:26 UTC, Joseph Rushton Wakeling wrote:
> I can prepare a reduced example but it's probably simpler for me to just prepare a bugfix and do some benchmarks.

By the way, CJS -- sorry to have hijacked your query.  But I think you had your answer already :-)
July 04, 2013
> By the way, CJS -- sorry to have hijacked your query.  But I think you had your answer already :-)

Yes. It was a very helpful answer. I'm just glad the question I asked was apparently relevant to other users as well.
July 04, 2013
On 07/04/2013 03:15 AM, Joseph Rushton Wakeling wrote:

> The cast should be safe, as it's a size_t to a double.

I am commenting without fully understanding the context: Both size_t and double are 64 bit types on a 64-bit system. double.mant_dig being 53, converting from size_t to double loses information for many values.

import std.stdio;
import std.conv;

void main()
{
    size_t i = 0x8000_0000_0000_0001;
    double d0 = i.to!double;
    double d1 = cast(double)i;

    writefln("%s", i);
    writefln("%f", d0);
    writefln("%f", d1);
}

Prints

9223372036854775809
9223372036854775808.000000
9223372036854775808.000000

Still, the same information loss in a comparison may make one think that it actually worked! :p

    assert(d0 == i);    // passes!
    assert(d1 == i);    // passes!

Ali

« First   ‹ Prev
1 2