Jump to page: 1 24  
Page
Thread overview
cast()x - a valid expression?
Jun 01, 2011
KennyTM~
Jun 01, 2011
Andrej Mitrovic
Jun 01, 2011
Andrej Mitrovic
Jun 01, 2011
KennyTM~
Jun 03, 2011
Stewart Gordon
Jun 03, 2011
Jonathan M Davis
Accidentally killing immutable is too easy in D (Was: cast()x - a valid expression?)
Jun 01, 2011
Nick Sabalausky
Jun 01, 2011
Jonathan M Davis
Re: Accidentally killing immutable is too easy in D (Was: cast()x - a
Jun 01, 2011
bearophile
Jun 01, 2011
Nick Sabalausky
Jun 02, 2011
Bruno Medeiros
Jun 02, 2011
Mehrdad
Jun 02, 2011
Mehrdad
Jun 02, 2011
Jonathan M Davis
Jun 02, 2011
Jonathan M Davis
Jun 02, 2011
Jonathan M Davis
Re: Accidentally killing immutable is too easy in D (Was: cast()x - a
Jun 03, 2011
bearophile
Jun 03, 2011
Jonathan M Davis
Jun 02, 2011
Jesse Phillips
Jun 02, 2011
Walter Bright
Jun 02, 2011
Andrej Mitrovic
Jun 02, 2011
Walter Bright
Jun 02, 2011
Nick Sabalausky
Jun 02, 2011
Bruno Medeiros
Jun 02, 2011
Andrej Mitrovic
Jun 02, 2011
Nick Sabalausky
Jun 02, 2011
Walter Bright
June 01, 2011
While checking the Phobos source I've found an interesting expression

      cast()(result[i]) = to!(E)(e);

The 'cast()' means 'cast to mutable', e.g.

      class S {}
      void g(S x) {}
      void main() {
         const S s;
         g(cast()s);
      }

But this is not documented in the D spec (CastParam cannot be empty). Is this an "accept-invalid" bug, or just a feature not yet documented?

June 01, 2011
It seems to do even more than that:

    int a;
    const int b;
    immutable int c;
    shared int d;
    shared(const int) e;

    static assert(is(typeof(cast()a) == int));
    static assert(is(typeof(cast()b) == int));
    static assert(is(typeof(cast()c) == int));
    static assert(is(typeof(cast()d) == int));
    static assert(is(typeof(cast()e) == int));

Talk about stealing the storm from std.traits.Unqual..

On 6/1/11, KennyTM~ <kennytm@gmail.com> wrote:
> While checking the Phobos source I've found an interesting expression
>
>        cast()(result[i]) = to!(E)(e);
>
> The 'cast()' means 'cast to mutable', e.g.
>
>        class S {}
>        void g(S x) {}
>        void main() {
>           const S s;
>           g(cast()s);
>        }
>
> But this is not documented in the D spec (CastParam cannot be empty). Is this an "accept-invalid" bug, or just a feature not yet documented?
>
>
June 01, 2011
On Wed, 01 Jun 2011 15:38:32 -0400, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:

> It seems to do even more than that:
>
>     int a;
>     const int b;
>     immutable int c;
>     shared int d;
>     shared(const int) e;
>
>     static assert(is(typeof(cast()a) == int));
>     static assert(is(typeof(cast()b) == int));
>     static assert(is(typeof(cast()c) == int));
>     static assert(is(typeof(cast()d) == int));
>     static assert(is(typeof(cast()e) == int));
>
> Talk about stealing the storm from std.traits.Unqual..
>
> On 6/1/11, KennyTM~ <kennytm@gmail.com> wrote:
>> While checking the Phobos source I've found an interesting expression
>>
>>        cast()(result[i]) = to!(E)(e);
>>
>> The 'cast()' means 'cast to mutable', e.g.
>>
>>        class S {}
>>        void g(S x) {}
>>        void main() {
>>           const S s;
>>           g(cast()s);
>>        }
>>
>> But this is not documented in the D spec (CastParam cannot be empty). Is
>> this an "accept-invalid" bug, or just a feature not yet documented?
>>
>>

It gets even better:

char[] x = "abc".dup;

assert(is(typeof(cast(const)x) == const(char[]));

I think you may have found a "bug" that should be a feature.  It's like dmd is organically growing features that we might need ;)  Is this software evolution?  Scary!

When will dmd decide that human life is a disease to be eradicated?  When will the world be dominated by constinators?!!!  I fear for my children.

All kidding aside, I actually think the syntax makes sense.  You are adding/removing modifiers, so just leave the type out of it.  The only drawback is, you can't do a cast directly to a tail-const array, but that's not a huge deal, since const(T[]) implicitly casts to const(T)[].

I dub this feature "Type Modifier Casting".

-Steve
June 01, 2011
On 6/1/11, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
> It gets even better:
>
> char[] x = "abc".dup;
> assert(is(typeof(cast(const)x) == const(char[]));

Nothing unusual about that?

DMD seems to be full of exciting little easter eggs! It's fun for the whole D family.
June 01, 2011
On Jun 2, 11 04:05, Steven Schveighoffer wrote:
> On Wed, 01 Jun 2011 15:38:32 -0400, Andrej Mitrovic
> <andrej.mitrovich@gmail.com> wrote:
>
>> It seems to do even more than that:
>>
>> int a;
>> const int b;
>> immutable int c;
>> shared int d;
>> shared(const int) e;
>>
>> static assert(is(typeof(cast()a) == int));
>> static assert(is(typeof(cast()b) == int));
>> static assert(is(typeof(cast()c) == int));
>> static assert(is(typeof(cast()d) == int));
>> static assert(is(typeof(cast()e) == int));
>>
>> Talk about stealing the storm from std.traits.Unqual..
>>
>> On 6/1/11, KennyTM~ <kennytm@gmail.com> wrote:
>>> While checking the Phobos source I've found an interesting expression
>>>
>>> cast()(result[i]) = to!(E)(e);
>>>
>>> The 'cast()' means 'cast to mutable', e.g.
>>>
>>> class S {}
>>> void g(S x) {}
>>> void main() {
>>> const S s;
>>> g(cast()s);
>>> }
>>>
>>> But this is not documented in the D spec (CastParam cannot be empty). Is
>>> this an "accept-invalid" bug, or just a feature not yet documented?
>>>
>>>
>
> It gets even better:
>
> char[] x = "abc".dup;
>
> assert(is(typeof(cast(const)x) == const(char[]));
>
> I think you may have found a "bug" that should be a feature. It's like
> dmd is organically growing features that we might need ;) Is this
> software evolution? Scary!
>
> When will dmd decide that human life is a disease to be eradicated? When
> will the world be dominated by constinators?!!! I fear for my children.
>
> All kidding aside, I actually think the syntax makes sense. You are
> adding/removing modifiers, so just leave the type out of it. The only
> drawback is, you can't do a cast directly to a tail-const array, but
> that's not a huge deal, since const(T[]) implicitly casts to const(T)[].
>
> I dub this feature "Type Modifier Casting".
>
> -Steve

cast(const), cast(immutable) etc are documented. cast() is not. See
http://d-programming-language.org/expression.html#CastExpression
June 01, 2011
"Steven Schveighoffer" <schveiguy@yahoo.com> wrote in message news:op.vwex37voeav7ka@localhost.localdomain...
> On Wed, 01 Jun 2011 15:38:32 -0400, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
>
>> It seems to do even more than that:
>>
>>     int a;
>>     const int b;
>>     immutable int c;
>>     shared int d;
>>     shared(const int) e;
>>
>>     static assert(is(typeof(cast()a) == int));
>>     static assert(is(typeof(cast()b) == int));
>>     static assert(is(typeof(cast()c) == int));
>>     static assert(is(typeof(cast()d) == int));
>>     static assert(is(typeof(cast()e) == int));
>>
>> Talk about stealing the storm from std.traits.Unqual..
>>
>> On 6/1/11, KennyTM~ <kennytm@gmail.com> wrote:
>>> While checking the Phobos source I've found an interesting expression
>>>
>>>        cast()(result[i]) = to!(E)(e);
>>>
>>> The 'cast()' means 'cast to mutable', e.g.
>>>
>>>        class S {}
>>>        void g(S x) {}
>>>        void main() {
>>>           const S s;
>>>           g(cast()s);
>>>        }
>>>
>>> But this is not documented in the D spec (CastParam cannot be empty). Is this an "accept-invalid" bug, or just a feature not yet documented?
>>>
>>>
>
> It gets even better:
>
> char[] x = "abc".dup;
>
> assert(is(typeof(cast(const)x) == const(char[]));
>
> I think you may have found a "bug" that should be a feature.  It's like dmd is organically growing features that we might need ;)  Is this software evolution?  Scary!
>
> When will dmd decide that human life is a disease to be eradicated?  When will the world be dominated by constinators?!!!  I fear for my children.
>
> All kidding aside, I actually think the syntax makes sense.  You are adding/removing modifiers, so just leave the type out of it.  The only drawback is, you can't do a cast directly to a tail-const array, but that's not a huge deal, since const(T[]) implicitly casts to const(T)[].
>
> I dub this feature "Type Modifier Casting".
>

It's nice in a way, but it's all based on the way cast handles modifiers. And I've always been a bit unconfortable with how that's handled (In fact, I was just thinking about this yesterday). Specifically, it seems extremely bad that it's so incredibly easy to accidentaly cast away things like const and immutable:

For example, if I know I have an array of uint's, and I want to deal with the individual bytes, it's perfectly safe and sensible to cast it to a ubyte[] (a long as you factor in endianness, of course). So, you do "cast(ubyte[])myArray". But, OOPS!!: If myArray happened to be immutable, then merely trying to cast the type has inadvertantly cast-away immutable. Not good! Casting away const/immutable really, really should have to be explict.

Of course, you can probably use some fancy helper templates to make sure you preserve all modifiers. But needing to do so is just asking for mistakes: it seems like a huge violation of "make the right way easy, and the wrong way hard".



June 01, 2011
On Wed, 01 Jun 2011 16:38:42 -0400, KennyTM~ <kennytm@gmail.com> wrote:

> On Jun 2, 11 04:05, Steven Schveighoffer wrote:
>> On Wed, 01 Jun 2011 15:38:32 -0400, Andrej Mitrovic
>> <andrej.mitrovich@gmail.com> wrote:
>>
>>> It seems to do even more than that:
>>>
>>> int a;
>>> const int b;
>>> immutable int c;
>>> shared int d;
>>> shared(const int) e;
>>>
>>> static assert(is(typeof(cast()a) == int));
>>> static assert(is(typeof(cast()b) == int));
>>> static assert(is(typeof(cast()c) == int));
>>> static assert(is(typeof(cast()d) == int));
>>> static assert(is(typeof(cast()e) == int));
>>>
>>> Talk about stealing the storm from std.traits.Unqual..
>>>
>>> On 6/1/11, KennyTM~ <kennytm@gmail.com> wrote:
>>>> While checking the Phobos source I've found an interesting expression
>>>>
>>>> cast()(result[i]) = to!(E)(e);
>>>>
>>>> The 'cast()' means 'cast to mutable', e.g.
>>>>
>>>> class S {}
>>>> void g(S x) {}
>>>> void main() {
>>>> const S s;
>>>> g(cast()s);
>>>> }
>>>>
>>>> But this is not documented in the D spec (CastParam cannot be empty). Is
>>>> this an "accept-invalid" bug, or just a feature not yet documented?
>>>>
>>>>
>>
>> It gets even better:
>>
>> char[] x = "abc".dup;
>>
>> assert(is(typeof(cast(const)x) == const(char[]));
>>
>> I think you may have found a "bug" that should be a feature. It's like
>> dmd is organically growing features that we might need ;) Is this
>> software evolution? Scary!
>>
>> When will dmd decide that human life is a disease to be eradicated? When
>> will the world be dominated by constinators?!!! I fear for my children.
>>
>> All kidding aside, I actually think the syntax makes sense. You are
>> adding/removing modifiers, so just leave the type out of it. The only
>> drawback is, you can't do a cast directly to a tail-const array, but
>> that's not a huge deal, since const(T[]) implicitly casts to const(T)[].
>>
>> I dub this feature "Type Modifier Casting".
>>
>> -Steve
>
> cast(const), cast(immutable) etc are documented. cast() is not. See
> http://d-programming-language.org/expression.html#CastExpression

:O

Of course, by documented, it shows the cast in the grammar (BTW, why the separate rule for cast(Type) when CastParam can be Type?), but not in the text.  I almost never read the grammar unless I'm confused by the docs.

This is almost as good as const_cast, although it seems too easy to screw up and remove const when you don't want to.

-Steve
June 01, 2011
On 2011-06-01 13:42, Nick Sabalausky wrote:
> "Steven Schveighoffer" <schveiguy@yahoo.com> wrote in message news:op.vwex37voeav7ka@localhost.localdomain...
> 
> > On Wed, 01 Jun 2011 15:38:32 -0400, Andrej Mitrovic
> > 
> > <andrej.mitrovich@gmail.com> wrote:
> >> It seems to do even more than that:
> >> int a;
> >> const int b;
> >> immutable int c;
> >> shared int d;
> >> shared(const int) e;
> >> 
> >> static assert(is(typeof(cast()a) == int));
> >> static assert(is(typeof(cast()b) == int));
> >> static assert(is(typeof(cast()c) == int));
> >> static assert(is(typeof(cast()d) == int));
> >> static assert(is(typeof(cast()e) == int));
> >> 
> >> Talk about stealing the storm from std.traits.Unqual..
> >> 
> >> On 6/1/11, KennyTM~ <kennytm@gmail.com> wrote:
> >>> While checking the Phobos source I've found an interesting expression
> >>> 
> >>> cast()(result[i]) = to!(E)(e);
> >>> 
> >>> The 'cast()' means 'cast to mutable', e.g.
> >>> 
> >>> class S {}
> >>> void g(S x) {}
> >>> void main() {
> >>> 
> >>> const S s;
> >>> g(cast()s);
> >>> 
> >>> }
> >>> 
> >>> But this is not documented in the D spec (CastParam cannot be empty). Is this an "accept-invalid" bug, or just a feature not yet documented?
> > 
> > It gets even better:
> > 
> > char[] x = "abc".dup;
> > 
> > assert(is(typeof(cast(const)x) == const(char[]));
> > 
> > I think you may have found a "bug" that should be a feature. It's like dmd is organically growing features that we might need ;) Is this software evolution? Scary!
> > 
> > When will dmd decide that human life is a disease to be eradicated? When will the world be dominated by constinators?!!! I fear for my children.
> > 
> > All kidding aside, I actually think the syntax makes sense. You are adding/removing modifiers, so just leave the type out of it. The only drawback is, you can't do a cast directly to a tail-const array, but that's not a huge deal, since const(T[]) implicitly casts to const(T)[].
> > 
> > I dub this feature "Type Modifier Casting".
> 
> It's nice in a way, but it's all based on the way cast handles modifiers. And I've always been a bit unconfortable with how that's handled (In fact, I was just thinking about this yesterday). Specifically, it seems extremely bad that it's so incredibly easy to accidentaly cast away things like const and immutable:
> 
> For example, if I know I have an array of uint's, and I want to deal with the individual bytes, it's perfectly safe and sensible to cast it to a ubyte[] (a long as you factor in endianness, of course). So, you do "cast(ubyte[])myArray". But, OOPS!!: If myArray happened to be immutable, then merely trying to cast the type has inadvertantly cast-away immutable. Not good! Casting away const/immutable really, really should have to be explict.
> 
> Of course, you can probably use some fancy helper templates to make sure you preserve all modifiers. But needing to do so is just asking for mistakes: it seems like a huge violation of "make the right way easy, and the wrong way hard".

You really shouldn't be casting much anyway. It's the sort of feature where you're only supposed to use it when you know what you're doing when you use it. And if there's really any possibility that you're dealing with immutable, perhaps you should be casting to const rather than mutable. Personally, I find how C++ created multiple types of cast (include const_cast) _highly_ annoying and generally useless, and I'm _very_ glad that D didn't do anything of the sort.

- Jonathan M Davis
June 01, 2011
On Wed, 01 Jun 2011 16:42:10 -0400, Nick Sabalausky <a@a.a> wrote:

> "Steven Schveighoffer" <schveiguy@yahoo.com> wrote in message
>> It gets even better:
>>
>> char[] x = "abc".dup;
>>
>> assert(is(typeof(cast(const)x) == const(char[]));
>>
>> I think you may have found a "bug" that should be a feature.  It's like
>> dmd is organically growing features that we might need ;)  Is this
>> software evolution?  Scary!
>>
>> When will dmd decide that human life is a disease to be eradicated?  When
>> will the world be dominated by constinators?!!!  I fear for my children.
>>
>> All kidding aside, I actually think the syntax makes sense.  You are
>> adding/removing modifiers, so just leave the type out of it.  The only
>> drawback is, you can't do a cast directly to a tail-const array, but
>> that's not a huge deal, since const(T[]) implicitly casts to const(T)[].
>>
>> I dub this feature "Type Modifier Casting".
>>
>
> It's nice in a way, but it's all based on the way cast handles modifiers.
> And I've always been a bit unconfortable with how that's handled (In fact, I
> was just thinking about this yesterday). Specifically, it seems extremely
> bad that it's so incredibly easy to accidentaly cast away things like const
> and immutable:

Yes, it would be nice to have the equivalent of static_cast (which doesn't allow removing const in C++).  I think however, we don't need compiler support for such things.  We can probably do this via metaprogramming.

However, having the ability to cast away or to const/immutable/shared/inout is very close to const_cast in C++.  It fixes the problem where you just want to cast away const but inadvertently end up switching the type.

We also need a static_cast for objects.  Right now, casting to a derived object involves a dynamic lookup, but if you know that the dynamic lookup is not necessary, a cast which does not do a dynamic lookup can be much faster.

For example, I could have a class A that contains a member of type X.  Then you implement B : A and Y : X such that B's member X is always actually a Y.  Re-storing the Y as another member is wasteful, and so is doing a dynamic cast for every usage of the member.

> Of course, you can probably use some fancy helper templates to make sure you
> preserve all modifiers. But needing to do so is just asking for mistakes: it
> seems like a huge violation of "make the right way easy, and the wrong way
> hard".

I get what you are saying.  I would be happy if default cast didn't allow casting away const or immutable, but I think we would have a difficult time introducing such a change.

Note however, C++ has good success with static_cast vs the old C-style cast (which is supported), so there is hope.  The more troubling thing is when you *want* to do a dynamic cast (which can only be done via the cast(X) style), you can inadvertently remove const or immutable.

-Steve
June 01, 2011
Jonathan M Davis:

> Personally, I find how C++ created multiple types of cast (include const_cast) _highly_ annoying and generally useless, and I'm _very_ glad that D didn't do anything of the sort.

Conflating all casts in a single syntax makes the D language look a bit simpler, but it also reduces the amount of expressivity and I suspect it may lead to some bugs (here Unqual helps). Changing the const state of a type is often orthogonal to changing its data type.

Thankfully D templates make it easy enough to build new types of cast. Time ago I have proposed a staticObjCast! for object references that performs some static sanity tests too. Unqual!() is another kind of cast, but it's a bit blunt. std.conv.to! is another kind of cast, that performs more complex conversions too. I am proposing to use to! for safe enum conversions too. A staticCast! that uses a locally defined enum sounds useful and safe.

Bye,
bearophile
« First   ‹ Prev
1 2 3 4