December 20, 2014
On Friday, 19 December 2014 at 15:17:04 UTC, Steven Schveighoffer wrote:
> On 12/18/14 6:18 PM, Adam D. Ruppe wrote:
>> On Thursday, 18 December 2014 at 23:06:12 UTC, ketmar via Digitalmars-d
>> wrote:
>>> the only thing this will help is to hide bugs, i believe.
>>
>> On the contrary, I find explicit casts hide bugs. Suppose you write:
>>
>> size_t a = cast(int) b;
>>
>> It will compile and run. It'll mostly work. But the cast to int probably
>> wasn't intended (it was probably written in 32 bit code and not
>> correctly ported to 64 bit).
>>
>> How often do we also write auto a = cast(T) b;? The difference would be
>> the type is written on the left side instead of the right. Might make an
>> important differnce when calling functions.
>>
>> I think the auto cast is a win all around.
>
> I have to agree with ketmar. Cast needs fixing, but this is not it. We need more control over what is cast, not less control.
>
> Your example unwittingly shows the issue :) casts are blunt instruments that force the compiler to abandon it's checks. I'm not as concerned about a changing it's type as I am about b. Change the type of b, and the compiler still happily generates possibly disastrous code.
>
> At this point, we can only say "abandon ALL checks." We can't finely tune this.

I'd like to have a cast where you must define both "from" and "to" types precisely.
December 20, 2014
It can be added trivially added to Phobos, of course, if more
people consider it useful.
December 20, 2014
On Sat, 20 Dec 2014 08:18:22 +0000
Jonathan Marler via Digitalmars-d <digitalmars-d@puremagic.com> wrote:

> Performing a grep on phobos reveals there are currently almost 3,000 casts.  I never like to use casts but they are a necessary evil.  I think anything D can do to help the programmer get their job done is a win.  The initial "pro" I saw for this idea was improving refactoribility.  I see this as a huge win.  You claim it will hide bugs?  Could you give an example?
autocasting to the types of function arguments is the immediate weak point. what you doing by this is destroying type checking. ok, we doing that from time to time, but you proposing handy sytax for it which will not break when function signature changes.

there is topic about "kind of programmers" nearby, where we found that "majority of programmers don't read books". and they tend to use the first tool they see to "make the job done", don't trying to evaluate the long-term consequences. i can assure you that you'll see `cast(auto)` all over their code, 'cause it's simply, it doesn't require even looking at function signature and trying to grasp why it accepts the given types, and "ah, it's so refactorable!" (they love "refactoring", 'cause they don't like to design their software, plus "refactoring" is often the blessed way to do nothing really valuable and still got payed).

besides, `cast` is a hack by itself. the good way to deal with hacks is to make them less powerful, not more powerful. you are proposing to make the hack more powerful. there is nothing bad in it... when the language is designed for use by hardcore hackers. but for languages with greater audience this is not a good way to go. hacks will inevitably be abused. it doesn't matter how many times we write in big letters: "PLEASE, DON'T DO THAT!" so hacks must be small and fine-grained, not small and powerful.

besides, `cast(auto)` is not decipherable without analyzing the
expression (and, possibly, function signature). it is not clear what
result of `cast(auto)` will be. this is bad for hack.

why `cast` is hack? 'cause it turns off most of the compiler type checking system. that's why we have `to!XXX` thing, which is not so disasterous. and compiler is smart enough to see that `a&0xff` is good for ubyte, for example.

we can't make `cast` less powerful now, but what we surely shouldn't do is making it more poweful.

> When I requested other people to chime in on this idea I was more looking for data/examples.  Maybe someone will think of an example that shows this idea could encourage bad coding practices?  Maybe it will hide bugs?  My point is, I don't want to discourage you from providing your opinion, but I  would really like to understand where your opinion comes from. I hope that wasn't harsh, I've read other posts you've made on the forums and although I don't agree with everything you say I would value your assessment. Thanks.
it comes from my past expirience. sometimes i just *sense* the smell. powerful hacks are great troublemakers. making Cassandra prophecies is my superpower. ;-)


December 20, 2014
On Saturday, 20 December 2014 at 10:14:10 UTC, bearophile wrote:
> Jonathan Marler:
>
>> if we allow return value types to be written as "auto" then it makes since to have cast(auto) as well.
>
> I think "cast(auto)" as I understand in your proposal introduces too often undefined situations, because in many cases the compiler can't know what's the type to cast to, and guessing is not acceptable. So I think it's not a good idea.

You gave one example of an 'undefined situation' (auto y = cast(auto)x). However this situation is clearly an error (not undefined). I think what you meant was that the type of auto is undefined, not the situation itself.  To this you are correct.  I fail to see why that makes this a bad idea. The whole concept of 'auto' is not defined in many situations but that doesn't make it a bad idea. If you were a programmer and you declared a variable y using auto, why would you think you need to cast it?

int x;
auto y = x;          // Normal
auto y = cast(int)x; // huh? there's not reason to do this

The only reason I could think of is when you want to explicitly say what type y should be.  But why would you do that using a cast? Just declare y as the type you want to be and skip 'auto'.

byte y = cast(byte)x;

Ah but now you have to keep the type of y and the cast "in sync".  So you could write this;

auto y = cast(byte)x;

It looks a little weird but it works.  I however think that if you want y to be a specific type, you should declare it as such (instead of using auto).

byte y = cast(byte)x;

We're back to the previous example. However now we are faced with the same problem of keeping the 2 types in sync. You could use cast(typeof(y)) to solve this, or you could use cast(auto).

byte y = cast(typeof(y))x;
byte y = cast(auto)x;

cast(auto) looks nicer but both  work fine.  The problem with cast(typeof(y)) is that it doesn't work when you are assigning x to an unnamed variable (like a function argument).

>
> But sometimes I have code like this:
>
> void main() {
>     int x;
>     byte y;
>     // ...
>     y = cast(typeof(y))x;
> }
>
>
> Here I want to cast x to the type of y to allow the assignment to y. This is perhaps an acceptable semantics for "cast(auto)":
>
>
> void main() {
>     int x;
>     byte y;
>     // ...
>     y = cast(auto)x; // OK
> }
>
>
> In that case the inference for the casting type is easy because the type of y is already defined. More examples:
>
>
> void foo(byte z) {}
> void main() {
>     int x;
>     // ...
>     auto y = cast(auto)x; // Error
>     byte y = cast(auto)x; // OK, but not very useful
>     foo(cast(auto)x);     // OK
> }
>
> Bye,
> bearophile-

Lastly I would like to say that cast(auto) provides a bit of functionality that is currently nowhere in the language.  It's not the same as cast(typeof(var)) since that cast needs a named variable to refer to. It would provide some functionality for templates that are currently nowhere in the langauge. I haven't thought of an example yet but if you think of one let me know:)
December 20, 2014
On Saturday, 20 December 2014 at 12:36:50 UTC, ketmar via Digitalmars-d wrote:
> On Sat, 20 Dec 2014 08:18:22 +0000
> Jonathan Marler via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
>> Performing a grep on phobos reveals there are currently almost 3,000 casts.  I never like to use casts but they are a necessary evil.  I think anything D can do to help the programmer get their job done is a win.  The initial "pro" I saw for this idea was improving refactoribility.  I see this as a huge win.  You claim it will hide bugs?  Could you give an example?
> autocasting to the types of function arguments is the immediate weak
> point.

I see this as one of it's strong points.  It provides greater refactoribility, and also has the potential for using casts inside templates to unnamed variables (like function arguments).

> ..what you doing by this is destroying type checking. ok, we doing
> that from time to time, but you proposing handy sytax for it which will
> not break when function signature changes.

casting is not destroying the type checking.  You can't convert a value to any type (an int to a struct), it still has to be possible.

struct MyStruct{...}
int x;
MyStruct s;
x = cast(int)s; // doesn't work
x = cast(auto)s; // still doesn't work

>
> there is topic about "kind of programmers" nearby, where we found that
> "majority of programmers don't read books". and they tend to use the
> first tool they see to "make the job done", don't trying to evaluate
> the long-term consequences. i can assure you that you'll see
> `cast(auto)` all over their code, 'cause it's simply, it doesn't
> require even looking at function signature and trying to grasp why it
> accepts the given types, and "ah, it's so refactorable!" (they love
> "refactoring", 'cause they don't like to design their software, plus
> "refactoring" is often the blessed way to do nothing really valuable
> and still got payed).

I'm not sure you'll get too many good programmers who agree with you that refactoring is only caused by "lack of design".  I'm not sure where to start when trying to list all the reasons someone would want to refactor.  New library, better design patter is realized, new feature has come in, new person has come in with a better solution, new api is introduced somewhere...so many reasons.  Programmer's aren't perfect, if we did everything right the first time then we never would have had c++ :)  D itself is just a refactor.

To address your other concern about seeing "cast(auto)" all over someone's code.  I think you might start seeing cast(auto) in place of some cast(T), but why would you start seeing cast(auto) in other places?  Nobody writes cast when it's unnecessary:

int x;
int y = cast(int)x;

Why would anyone do this?  Don't tell me it's because the programmer is too stupid to know what a cast means, you could make that same argument for any feature.  Some languages have used that argument to remove any number of unsafe features like pointer arithmetic, non-garbage collected memory, etc.  The purpose of D is not to restrict the programmer so they can't make any mistakes, it's purpose is to make programming easier and of course safer but not at the expense of removing the ability to do the unsafe operations when needed. It is true that 'cast' reduces type checking, but it doesn't remove it and it's also necessary.

>
> besides, `cast` is a hack by itself. the good way to deal with hacks is
> to make them less powerful, not more powerful. you are proposing to
> make the hack more powerful. there is nothing bad in it... when the
> language is designed for use by hardcore hackers. but for languages
> with greater audience this is not a good way to go. hacks will
> inevitably be abused. it doesn't matter how many times we write in big
> letters: "PLEASE, DON'T DO THAT!" so hacks must be small and
> fine-grained, not small and powerful.

cast is not a hack, it's a necessary feature that is well defined.  It reduces type safety, which may be why you are calling it a "hack", but unfortunately it is necessary.  cast(auto) is a natural extension to a necessary feature that's not going to go away. Type safety is not a simple problem.  The more type safe you get the more restrictive your language gets, which causes more need for casting.  The less type safe your language is, the less casting you need but then the more unsafe your whole program becomes.  D often chooses to make 90% of code safe and provides ways for you to escape the safety of the language for the extra 10%.  Cast falls into the category of the 10%. If you go through some examples I think you'll find that cast(auto) used in the cases where it makes sense actually produces code that results in less bugs.  But like any tool, of course it can be misused, but that's not a reason to not have it.

>
> besides, `cast(auto)` is not decipherable without analyzing the
> expression (and, possibly, function signature). it is not clear what
> result of `cast(auto)` will be. this is bad for hack.
>

Normal auto declarations and using auto as a return type has the same problem. But sometimes you don't care what the type is.  If you always needed to know what type something is then templates wouldn't exist.

> why `cast` is hack? 'cause it turns off most of the compiler type
> checking system. that's why we have `to!XXX` thing, which is not so
> disasterous. and compiler is smart enough to see that `a&0xff` is good
> for ubyte, for example.

Again, it doesn't "turn off" type checking, it makes types checking more lenient which is sometimes necessary.

>
> we can't make `cast` less powerful now, but what we surely shouldn't do
> is making it more poweful.

You're right we can't make it less powerful because it's necessary.  If you have an idea on how D could get rid of it we would all love to hear it:)

>
>> When I requested other people to chime in on this idea I was more looking for data/examples.  Maybe someone will think of an example that shows this idea could encourage bad coding practices?  Maybe it will hide bugs?  My point is, I don't want to discourage you from providing your opinion, but I  would really like to understand where your opinion comes from. I hope that wasn't harsh, I've read other posts you've made on the forums and although I don't agree with everything you say I would value your assessment. Thanks.
> it comes from my past expirience. sometimes i just *sense* the smell.
> powerful hacks are great troublemakers. making Cassandra prophecies is
> my superpower. ;-)

December 20, 2014
On Sat, 20 Dec 2014 18:19:21 +0000
Jonathan Marler via Digitalmars-d <digitalmars-d@puremagic.com> wrote:

> > we can't make `cast` less powerful now, but what we surely
> > shouldn't do
> > is making it more poweful.
> 
> You're right we can't make it less powerful because it's necessary.  If you have an idea on how D could get rid of it we would all love to hear it:)

something like modula's "system" module: if you need `cast`, or pointers, or other "low-level" things, you should import "system" module. and you HAVE to write `system.cast(...)`. make it cumbersome! let `to!XXX` do the work, with all it's checks. making unsafe features easier to use is a way to spread their usage, and i see it as a "generally bad thing".


December 20, 2014
On Saturday, 20 December 2014 at 19:00:57 UTC, ketmar via Digitalmars-d wrote:
> On Sat, 20 Dec 2014 18:19:21 +0000
> Jonathan Marler via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
>> > we can't make `cast` less powerful now, but what we surely shouldn't do
>> > is making it more poweful.
>> 
>> You're right we can't make it less powerful because it's necessary.  If you have an idea on how D could get rid of it we would all love to hear it:)
>
> something like modula's "system" module: if you need `cast`, or
> pointers, or other "low-level" things, you should import "system"
> module. and you HAVE to write `system.cast(...)`. make it cumbersome!
> let `to!XXX` do the work, with all it's checks. making unsafe features
> easier to use is a way to spread their usage, and i see it as a
> "generally bad thing".

Hmmmm...an interesting concept.  Make unsafe things harder to do to discourage their use.  I'm not sure if I agree but maybe you can convince me. Where do you draw the line?  If you wanted to make these features harder to use why not make the user type the word cast in a different language like Japanese?  Or why not take cast out all together and force the developer to use assembly or another language?  You said you could make the user import an unsafe module, why not go a step further and have them type in a password, or have them write out a long specific sequence to perform the cast:

byte x = cast$%*%@*@(*#&&!(($)$@)@$(@($)@$$*@(@**(!(byte) y;

I don't agree that making things harder to use is a good idea, but I do agree that making things more verbose can be a good idea to prevent misuse.  It makes sense because in order to use cast you should know what it means and if you know what it means you should know the verbose syntax to use it.  That concept makes sense.  But in my opinion, the "cast" keyword is enough.  It provides a way to audit your code by grepping for the "cast" keyword, and any programmer that sees the word cast and doesn't understand it will likely look up what it means.  I could get on board with adding a restriction that you tell the compiler somehow that you are going to use casts in your file (like importing the "system" module), but when you go to use it, I don't think it should be "harder" to use.  cast(auto) may be easier to use but it also makes more sense in some cases.  I've listed some of the cases in my other posts but the general idea is it requires less maintenance. Say you have the following:

void myfunc(uint x)
{
    ubyte val;
    //
    // ...
    //
    val = cast(ubyte)x;
}

Now let's say that you need change the value of 'val' to ushort.

void myfunc(uint x)
{
    ushort val;
    //
    // ...
    //
    val = cast(ubyte)x;
}

Now we have a bug that could be incredibly difficult to find and will likely not be found through typical unit testing.  It will probably result in weird unexpected runtime crashes as the invalid cast error propogates through the program until something throws an exception.  The error is caused by having to write the same thing in 2 different places.  You have to write the type of 'val' in the declaration and in the cast. This could have been avoided if you used cast(typeof(val)), but what if the name of val changes?  Then you have the same situation if another variable get's renamed to 'val'.  If you use cast(auto) you don't need to maintain the type in both places.  It prevents this particular bug.

Now I'm not saying that cast(auto) is good in all cases, I'm just trying to get you to see the big picture here.  cast(auto) could be useful and could help prevent maintenance bugs in SOME cases.  Yes it can be misused, but I don't agree that making it harder to use is a good way to prevent misusage, but requiring more verbosity is good.  You may disagree that "cast" is enough verbosity but I think that's a matter of opinion.





December 20, 2014
On Sat, 20 Dec 2014 19:26:54 +0000
Jonathan Marler via Digitalmars-d <digitalmars-d@puremagic.com> wrote:

> Hmmmm...an interesting concept.  Make unsafe things harder to do to discourage their use.  I'm not sure if I agree but maybe you can convince me. Where do you draw the line?
the thing is that they aren't only harder to use, but they are also explicitly marked as "system" things. i.e. things that should be used only if you are *really* know what you're doing.

besides, code with `system.cast()` looks suspiciously "burden", which also signals that this is not a thing one should mindlessly use everywhere.

something like that.

> is it requires less maintenance. Say you have the following:
> 
> void myfunc(uint x)
> {
>      ubyte val;
>      //
>      // ...
>      //
>      val = cast(ubyte)x;
> }
> 
> Now let's say that you need change the value of 'val' to ushort.
> 
> void myfunc(uint x)
> {
>      ushort val;
>      //
>      // ...
>      //
>      val = cast(ubyte)x;
> }
why do you need `cast` here? isn't `to!ubyte` looks better? and it's not only looks better, it will provide you additional overflow checks too. so if you'll throw a '1024' in your unittest, the second version will fail, signalling that something is going wrong.

> Now I'm not saying that cast(auto) is good in all cases, I'm just trying to get you to see the big picture here.  cast(auto) could be useful and could help prevent maintenance bugs in SOME cases.
i see that `cast` should NOT be used in that cases at all. and this returns us to "`cast` is hack. avoid the hacks!"

> Yes it can be misused, but I don't agree that making it harder to use is a good way to prevent misusage, but requiring more verbosity is good.  You may disagree that "cast" is enough verbosity but I think that's a matter of opinion.
sure, i'm just talking about what i see as "good", i'm in no way trying to tell that my opinion is the best one. sorry if my words are too "forcing". i'm a somewhat sarcastic person IRL, and i don't use English in my everyday life, so i can sound too hard sometimes, failing to properly translate my twisted style of writing. ;-)


December 20, 2014
On Saturday, 20 December 2014 at 19:57:54 UTC, ketmar via Digitalmars-d wrote:
> On Sat, 20 Dec 2014 19:26:54 +0000
> Jonathan Marler via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
>> Hmmmm...an interesting concept.  Make unsafe things harder to do to discourage their use.  I'm not sure if I agree but maybe you can convince me. Where do you draw the line?
> the thing is that they aren't only harder to use, but they are also
> explicitly marked as "system" things. i.e. things that should be used
> only if you are *really* know what you're doing.
>
> besides, code with `system.cast()` looks suspiciously "burden", which
> also signals that this is not a thing one should mindlessly use
> everywhere.
>
> something like that.
>
>> is it requires less maintenance. Say you have the following:
>> 
>> void myfunc(uint x)
>> {
>>      ubyte val;
>>      //
>>      // ...
>>      //
>>      val = cast(ubyte)x;
>> }
>> 
>> Now let's say that you need change the value of 'val' to ushort.
>> 
>> void myfunc(uint x)
>> {
>>      ushort val;
>>      //
>>      // ...
>>      //
>>      val = cast(ubyte)x;
>> }
> why do you need `cast` here? isn't `to!ubyte` looks better? and it's
> not only looks better, it will provide you additional overflow checks
> too. so if you'll throw a '1024' in your unittest, the second version
> will fail, signalling that something is going wrong.
>

Ah yes you are right, to!byte would make more sense because you check at runtime whether or not x is within the range of a byte.  This would make the code crash right away instead of having to track down the bug but you still wouldn't see the bug until runtime, and may only happen in rare cases that only occur in the customer environment.  to!(typeof(val)) would also handle changing the type when the type of val changes.  It looks awkward though.  It would be nice if "to" handled type inference.

val = to(x);
// instead of val = to!(typeof(val)(x);
// or
val = to!auto(x); // Impossible right now since compiler doesn't understand "to"

"val = to!auto(x)" could be useful in some cases but this would be the same basic concept as cast(auto) except "to" allows for more "sanity" checking.  I'd have to think more about cases where cast(auto) would be useful but this is starting to take too much of my time so I'll leave that to other people if they want to take time to do so.  I've invested enough time into this and if no one else wants to support it then no big deal.  Like I said, this would only be a minor convenience.

>> Now I'm not saying that cast(auto) is good in all cases, I'm just trying to get you to see the big picture here.  cast(auto) could be useful and could help prevent maintenance bugs in SOME cases.
> i see that `cast` should NOT be used in that cases at all. and this
> returns us to "`cast` is hack. avoid the hacks!"
>
>> Yes it can be misused, but I don't agree that making it harder to use is a good way to prevent misusage, but requiring more verbosity is good.  You may disagree that "cast" is enough verbosity but I think that's a matter of opinion.
> sure, i'm just talking about what i see as "good", i'm in no way trying
> to tell that my opinion is the best one. sorry if my words are too
> "forcing". i'm a somewhat sarcastic person IRL, and i don't use English
> in my everyday life, so i can sound too hard sometimes, failing to
> properly translate my twisted style of writing. ;-)

I don't mind your style of writing, some people might be offended by it but it doesn't bother me.  When discussing technical details it takes a lot of effort to be polite and I'd rather you spend that effort in making the details more correct rather then trying to be "tactful".
December 21, 2014
On 12/20/14 5:20 AM, Dicebot wrote:

> I'd like to have a cast where you must define both "from" and "to" types
> precisely.

I was actually thinking the same thing. This would be almost future-proof (any changes to either side would result in failed compilation).

-Steve