digitalmars.D - The cast(signed), cast(unsigned) feature proposal
- Mrzlga (42/42) Jun 07 2013 Hi guys,
- Adam D. Ruppe (8/14) Jun 07 2013 I think this is a really strong counterargument and one I'd like
- Andrei Alexandrescu (6/11) Jun 07 2013 http://dlang.org/phobos/std_traits.html#.unsigned
- Mrzlga (7/7) Jun 07 2013 A reason for cast(signed) is to discourage the user from writing:
- Jesse Phillips (3/11) Jun 07 2013 Not convenient, but:
- Idan Arye (16/32) Jun 07 2013 How about this: if `Foo` is a template with a single type
- Idan Arye (2/3) Jun 07 2013 Should be "not as good as the syntactic sugar solution"
- Mrzlga (13/16) Jun 07 2013 My proposal has a bad thing about it:
- Mrzlga (12/12) Jun 07 2013 "doing nothing but converting unsigned->signed" is a dubious
- Timothee Cour (30/39) Jun 07 2013 I'm against it since we can do it better in library with same efficiency
- Mrzlga (18/18) Jun 07 2013 Timothy,
- Timothee Cour (10/28) Jun 07 2013 not suggesting deprecating cast(), just suggesting there's no need to
- Mrzlga (7/14) Jun 07 2013 I don't think you can simultaneously try to not-suggest
- Timothee Cour (12/24) Jun 07 2013 the point is to avoid breaking code.
- Idan Arye (18/30) Jun 07 2013 So, you want a syntactic salt that will force people to write
- Mrzlga (4/5) Jun 07 2013 No, no, I don't actually want the salt. I hoped I had indicated
- Mrzlga (8/8) Jun 07 2013 I don't know the story of how D resolved to not provide 'ulong'
- Timothee Cour (14/32) Jun 07 2013 not to mention its much harder to implement in language, whereas its
- timotheecour (6/57) Jun 07 2013 not to mention its much harder and bug-prone to implement in
- Idan Arye (7/13) Jun 07 2013 So, let me get this straight:
- Mrzlga (28/34) Jun 07 2013 - I do want cast(signed)
- Walter Bright (3/5) Jun 07 2013 Not/*"*/"*/that
- Mrzlga (10/10) Jun 07 2013 Andrei, what do you think about the unsigned(x) not showing up on
- Andrei Alexandrescu (5/15) Jun 07 2013 Grepping is useful for identifying dangerous patterns. What a dangerous
- Marco Leise (15/33) Jun 07 2013 That made me scratch my head again. I thought
- monarch_dodra (12/14) Jun 07 2013 FWI, you can use std.trait's Signed and Unsigned as a partial
- monarch_dodra (5/20) Jun 07 2013 EDIT: Couldn't find it. Must have been my imagination. Didn't
- deadalnix (2/4) Jun 08 2013 This !
Hi guys, This is a small feature proposal. Please consider to add these to the language: cast(signed) cast(unsigned) Motivation: - To remove the need to write "cast(ulong) x" and repeat the underlying type, which is the same motivation as cast(const), cast(immutable), cast(shared) - Reduce the strain of writing signed/unsigned conversions, so that making signed/unsigned conversions a compilation error is more palatable. - Works as a new feature: if we have created a function or template which uses Concepts to accept just a signed number, we can use cast(unsigned) to generically cast any type X to the unsigned version. Positives: - cast(signed) is easy to type. - cast(signed) is easy to see -- Scanning over the code with your eyes, we can see that the only intention was to make a cast about the signedness, but not about anything else. - Works within the system of grepping for all casts. - Works in the spirit of 'auto'. - Consistent with cast(const), cast(immutable), cast(shared). Downsides: - Adds two keywords to the language. > They aren't the worst keywords, considering that C has them. - 'unsigned already means something in C, let's not change how it works' - Writing "cast(unsigned) x" is actually more text than "cast(ulong) x" > True, but the cast(unsigned) expresses the intention Possible arguments against: - The idea of 'no casts should be generic' - Use the library for it and instead make signed(x), unsigned(x) templates. > Downsides to this solution: User can't easily grep for 'cast' and find the 'unsigned(x)' template. It should be consistently greppable in the exact same way as other casts. Because it is a cast, so don't hide it. That's it! Thanks for your consideration :)
Jun 07 2013
On Friday, 7 June 2013 at 20:52:53 UTC, Mrzlga wrote:- Use the library for it and instead make signed(x), unsigned(x) templates.I think this is a really strong counterargument and one I'd like to see done, along with other kinds of casts in the library.> Downsides to this solution: User can't easily grep for 'cast' and find the 'unsigned(x)' template. It should be consistently greppable in the exact same way as other casts. Because it is a cast, so don't hide it.I would name it cast_to_unsigned or signed_cast or something like that. Then the word "cast" is still there. Most of phobos uses camelCase so underscores might be weird, but it is a cast, it is supposed to be a little weird, and besides, I can't get C++'s various_casts out of my mind.
Jun 07 2013
On 6/7/13 4:52 PM, Mrzlga wrote:Hi guys, This is a small feature proposal. Please consider to add these to the language: cast(signed) cast(unsigned)We should prolly add signed() as well. Could you please author an enhancement request (and at best a pull request too)? Thanks, Andrei
Jun 07 2013
A reason for cast(signed) is to discourage the user from writing: cast(int) x; Because we can't grep for the word "signed", We have to search for "cast( )" only! cast(int) x // hides the intention, hard to search for! Yet we can easily grep for: cast(signed)
Jun 07 2013
On Friday, 7 June 2013 at 21:34:00 UTC, Mrzlga wrote:A reason for cast(signed) is to discourage the user from writing: cast(int) x; Because we can't grep for the word "signed", We have to search for "cast( )" only! cast(int) x // hides the intention, hard to search for! Yet we can easily grep for: cast(signed)Not convenient, but: cast(Signed!(typeof(x))
Jun 07 2013
On Friday, 7 June 2013 at 21:42:05 UTC, Jesse Phillips wrote:On Friday, 7 June 2013 at 21:34:00 UTC, Mrzlga wrote:How about this: if `Foo` is a template with a single type parameter that returns a type, writing `cast(Foo)bar` will be parsed as `cast(Foo!(typeof(bar))bar`. This will allow as to write `cast(Signed)x` - no need for extra keywords - and it will also allow us to write more generic things, like `cast(Nullable)(x)` will return a `typeof(x)` `Nullable` that holds the value of `x` - whatever that value may be. I've written a simple function that does that: auto Cast(alias Template,T)(T source){ return cast(Template!T)(source); } And it works, but not as good as the template solution since `typeof(Cast!Nullable(0))` returns `Template!(int)` instead of `Nullable!(int)`.A reason for cast(signed) is to discourage the user from writing: cast(int) x; Because we can't grep for the word "signed", We have to search for "cast( )" only! cast(int) x // hides the intention, hard to search for! Yet we can easily grep for: cast(signed)Not convenient, but: cast(Signed!(typeof(x))
Jun 07 2013
On Friday, 7 June 2013 at 22:05:46 UTC, Idan Arye wrote:but not as good as the template solutionShould be "not as good as the syntactic sugar solution"
Jun 07 2013
How about this: if `Foo` is a template with a single type parameter that returns a type, writing `cast(Foo)bar` will be parsed as `cast(Foo!(typeof(bar))bar`.My proposal has a bad thing about it: The 'unsigned' and 'signed' keywords can't be as easily extended the way that an signed(x) template in the library can: A library author could just specialize the signed() template to add support for their own numeric type. To do the same with cast(signed) it needs to invoke some signed operator on the type, or use your solution. I wanted to deal with the cast(int) x; not showing the intention of "signed". If your cast(SomeTemplate) solution can handle this as well, then it's better. I don't actually mind writing signed(x), but I want to think of a way to discourage people from writing cast(int) x when they are doing nothing but converting unsigned->signed.
Jun 07 2013
"doing nothing but converting unsigned->signed" is a dubious statement. They are still screwing with the range, they are not just "doing nothing but converting unsigned->signed". And 'int' says something about the outcome. So I am really asking for: cast(signed int) x; // make them poor programmers write this, lol That's not what I actually want, but at least it shows: We're making a signed conversion, AND we're screwing with the range to make it into an int. for further thought.
Jun 07 2013
I'm against it since we can do it better in library with same efficiency and better UFCS syntax: see https://github.com/timotheecour/dtools/blob/master/dtools/util/cast_funs.d to test it, nothing to install, just type: rdmd --main -unittest dtools/all.d here's the unittest: ---- version(unittest){ import std.stdio; int foo(int x){ return x; } } unittest{ double c; // auto b1=cast(int)c.foo;//means cast(int)(c.foo), so would be CT error auto b2=(cast(int)c).foo;//verbose syntax: 2 nested parenthesis auto b3=c.Cast!int.foo;//simpler syntax int a=1; auto b=(a+a).Cast!double; static assert(is(typeof(b)==double)); static assert(is(typeof(a.Cast!Immutable)==immutable(int))); static assert(is(typeof(a.Cast!Const)==const(int))); static assert(is(typeof(0U.Cast!Signed)==int)); static assert(is(typeof(a.Cast!Unsigned)==uint)); static assert(is(typeof(a.Cast!Const)==const(int))); static assert(is(typeof((a+a).Cast!Unsigned)==uint)); } ---- On Fri, Jun 7, 2013 at 5:43 PM, Mrzlga <bulletproofchest gmail.com> wrote:"doing nothing but converting unsigned->signed" is a dubious statement. They are still screwing with the range, they are not just "doing nothing but converting unsigned->signed". And 'int' says something about the outcome. So I am really asking for: cast(signed int) x; // make them poor programmers write this, lol That's not what I actually want, but at least it shows: We're making a signed conversion, AND we're screwing with the range to make it into an int. for further thought.
Jun 07 2013
Timothy, How do you get everyone to use: a.Cast!Signed a.Cast!Unsigned a.Cast!Const a.Cast!Immutable a.Cast!Shared And to stop using: cast(const) cast(immutable) cast(shared) cast(inout) ? And have everyone be consistent about it? Remove the cast() ones from the language? And what about variations, 'shared const', 'inout shared', etc? There are some things that should be available to the language, even when no modules are imported. I think dealing with the basic type system is like that.
Jun 07 2013
On Fri, Jun 7, 2013 at 6:53 PM, Mrzlga <bulletproofchest gmail.com> wrote:Timothy, How do you get everyone to use: a.Cast!Signed a.Cast!Unsigned a.Cast!Const a.Cast!Immutable a.Cast!Shared And to stop using: cast(const) cast(immutable) cast(shared) cast(inout) ? And have everyone be consistent about it? Remove the cast() ones from the language?not suggesting deprecating cast(), just suggesting there's no need to extend the language as it can be done in library code, advantageously. It's trivially extensible as I wrote it. However, any language extension has to be re-implemented by each compiler implementation.And what about variations, 'shared const', 'inout shared', etc?it's trivial to add to my code a.Cast!"shared const" or a.Cast!SharedConst, etc, as well as more complex ones.There are some things that should be available to the language, even when no modules are imported. I think dealing with the basic type system is like that.Not if the syntax sugar provided by the language is no simple than that provided by library solution. I've argued library solution is more consistent with UFCS (see my code).
Jun 07 2013
not suggesting deprecating cast(), just suggesting there's no need to extend the language as it can be done in library code, advantageously. It's trivially extensible as I wrote it. However, any language extension has to be re-implemented by each compiler implementation.I don't think you can simultaneously try to not-suggest deprecating cast() shortcuts, and do-suggest there's no need to extend the language as it can be done in library code, while suggestiing duplicating cast() shortcuts. Your point would make sense if you were trying to get rid of the shortcuts. Otherwise you should argue for signed(x) / unsigned(x) Make it consistent.
Jun 07 2013
the point is to avoid breaking code. Since no-one can possibly use cast(unsigned) currently, introducing Cast and recommending using Cast instead of cast() will not break any code and provide room for library based cast extensions. The smaller the symbols in scope and the shorter the syntax the better; I doubt you're using cast() in all your modules anyways. However, I very much do support language syntax sugar when it provides advantages over a library solution: * tuples (see DIP), * named parameter argument (see threads) * and even to some extent := (your suggestion!) On Fri, Jun 7, 2013 at 7:24 PM, Mrzlga <bulletproofchest gmail.com> wrote:not suggesting deprecating cast(), just suggesting there's no need toextend the language as it can be done in library code, advantageously. It's trivially extensible as I wrote it. However, any language extension has to be re-implemented by each compiler implementation.I don't think you can simultaneously try to not-suggest deprecating cast() shortcuts, and do-suggest there's no need to extend the language as it can be done in library code, while suggestiing duplicating cast() shortcuts. Your point would make sense if you were trying to get rid of the shortcuts. Otherwise you should argue for signed(x) / unsigned(x) Make it consistent.
Jun 07 2013
On Saturday, 8 June 2013 at 00:43:28 UTC, Mrzlga wrote:"doing nothing but converting unsigned->signed" is a dubious statement. They are still screwing with the range, they are not just "doing nothing but converting unsigned->signed". And 'int' says something about the outcome. So I am really asking for: cast(signed int) x; // make them poor programmers write this, lol That's not what I actually want, but at least it shows: We're making a signed conversion, AND we're screwing with the range to make it into an int. for further thought.So, you want a syntactic salt that will force people to write `cast(singed int)` instead of `cast(int)` and `cast(unsigned int)` instead of `cast(uint)`? What if they are not casting from a number? What if I want the ASCII value of a character - for example, `cast(int)'a'`? Will I have to write `cast(signed int)'a'`, or is this syntactic salt just for casting from numeric types? I'm against this syntactic salt proposal. Programmers should know that `int` is signed and `uint` is unsigend, and I see little point in forcing them to acknowledge that whenever they do a numeric cast. Also, casting to unsigned with implicit type is dangerous, since cast(uint)-1 == 4294967295 != 18446744073709551615 == cast(ulong)-1, but casting to signed is less dangerous, since it only affects large numbers. So the syntactic salt is more important for `cast(uint)` than for `cast(int)` - but `unit` already clarifies that the type is unsigned.
Jun 07 2013
So, you want a syntactic salt that will force people to writeNo, no, I don't actually want the salt. I hoped I had indicated that in my message. It was only for your consideration about cast(int), how it would be nice to "indicate everything" if there was no price to it.
Jun 07 2013
I don't know the story of how D resolved to not provide 'ulong' and 'unsigned long' as equivalent, but I do understand the motivation to keep things short and standard, with 1-word-per-basic-type. I should say one thing though, In C / C++: unsigned x = f(); // this was traumatic. "unsigned" was an actual type itself, not just a type qualifier.
Jun 07 2013
not to mention its much harder to implement in language, whereas its trivial in the library. Also, it makes instrumentation easier, if one wants to add a callback/logging/breakpoint for a particular cast operation. Seems much harder with language solution. On Fri, Jun 7, 2013 at 6:53 PM, Mrzlga <bulletproofchest gmail.com> wrote:Timothy, How do you get everyone to use: a.Cast!Signed a.Cast!Unsigned a.Cast!Const a.Cast!Immutable a.Cast!Shared And to stop using: cast(const) cast(immutable) cast(shared) cast(inout) ? And have everyone be consistent about it? Remove the cast() ones from the language?not suggesting deprecating cast(), just suggesting there's no need to extend the language as it can be done in library code, advantageously. It's trivially extensible as I wrote it. However, any language extension has to be re-implemented by each compiler implementation.And what about variations, 'shared const', 'inout shared', etc?it's trivial to add to my code a.Cast!"shared const" or a.Cast!SharedConst, etc, as well as more complex ones.There are some things that should be available to the language, even when no modules are imported. I think dealing with the basic type system is like that.Not if the syntax sugar provided by the language is no simple than that provided by library solution. I've argued library solution is more consistent with UFCS (see my code).
Jun 07 2013
On Saturday, 8 June 2013 at 02:21:01 UTC, Timothee Cour wrote:not to mention its much harder to implement in language, whereas its trivial in the library. Also, it makes instrumentation easier, if one wants to add a callback/logging/breakpoint for a particular cast operation. Seems much harder with language solution. On Fri, Jun 7, 2013 at 6:53 PM, Mrzlga <bulletproofchest gmail.com> wrote:not to mention its much harder and bug-prone to implement in language, whereas its trivial in the library. Also, it makes instrumentation easier, if one wants to add a callback/logging/breakpoint for a particular cast operation. Seems much harder with language solution.Timothy, How do you get everyone to use: a.Cast!Signed a.Cast!Unsigned a.Cast!Const a.Cast!Immutable a.Cast!Shared And to stop using: cast(const) cast(immutable) cast(shared) cast(inout) ? And have everyone be consistent about it? Remove the cast() ones from the language?not suggesting deprecating cast(), just suggesting there's no need to extend the language as it can be done in library code, advantageously. It's trivially extensible as I wrote it. However, any language extension has to be re-implemented by each compiler implementation.And what about variations, 'shared const', 'inout shared', etc?it's trivial to add to my code a.Cast!"shared const" or a.Cast!SharedConst, etc, as well as more complex ones.There are some things that should be available to the language, even when no modules are imported. I think dealing with the basic type system is like that.Not if the syntax sugar provided by the language is no simple than that provided by library solution. I've argued library solution is more consistent with UFCS (see my code).
Jun 07 2013
On Saturday, 8 June 2013 at 01:58:46 UTC, Mrzlga wrote:So, let me get this straight: * You don't want `cast(signed)`, because of the range difference between the types. * You want `cast(signed int)` but not as syntactic salt - which means you still want `cast(int)` to work. How about `cast(/*signed*/ int)`?So, you want a syntactic salt that will force people to writeNo, no, I don't actually want the salt. I hoped I had indicated that in my message. It was only for your consideration about cast(int), how it would be nice to "indicate everything" if there was no price to it.
Jun 07 2013
So, let me get this straight: * You don't want `cast(signed)`, because of the range difference between the types. * You want `cast(signed int)` but not as syntactic salt - which means you still want `cast(int)` to work. How about `cast(/*signed*/ int)`?- I do want cast(signed) - I don't want to suggest cast(int) should not work, but rather to think of a solution for better documentation in the code, and to encourage people to write: cast(signed) // when they're casting unsigned->signed cast(int) // when they're casting short->int - I still feel slightly uneasy about the previous point. What I mentioned about cast(signed int) was a form of brainstorming. I wanted to try to give some consideration to people who'd want the destination datatype to be explicit, as it says something about the destination range. However, the fact that we must be careful of the range is already implied by cast(signed) and cast(unsigned). - I like how cast(const) uses the lowercase const and the same const keyword. There's a nice consistency about that. So I don't want them in the library. - Cast operations should be available without module imports. - I would use the cast(signed) and feel comfortable. - I could use the signed(x) and enjoy it! cast(signed) is not a super important thing like the := - I think *your* idea was good and possibly better than mine, as it allows library authors to create new numerical types that support signed/unsigned casting, and yet still access it via cast(signed) if 'signed' was the template. - I'm not sure if Walter & Andrei would want cast(ToWorkWithTheTemplates). Regards, z
Jun 07 2013
On 6/7/2013 2:33 PM, Mrzlga wrote:Yet we can easily grep for: cast(signed)Not/*"*/"*/that easy
Jun 07 2013
Andrei, what do you think about the unsigned(x) not showing up on greps for 'cast'? No problem? Is the grep irrelevant? Not all casts should be marked as a cast? People told me the grepping was important, so I tried to work their idea in. I understand, you can still search for: "signed(" // signed or unsigned "cast(u" // unsigned "cast( ... every type ... )" // trying to find signed conversions But I was trying to make the thing more predictable altogether.
Jun 07 2013
On 6/7/13 5:41 PM, Mrzlga wrote:Andrei, what do you think about the unsigned(x) not showing up on greps for 'cast'? No problem? Is the grep irrelevant? Not all casts should be marked as a cast? People told me the grepping was important, so I tried to work their idea in. I understand, you can still search for: "signed(" // signed or unsigned "cast(u" // unsigned "cast( ... every type ... )" // trying to find signed conversions But I was trying to make the thing more predictable altogether.Grepping is useful for identifying dangerous patterns. What a dangerous pattern is varies according to the person, but it's not possible to grep for everything that everyone considers dangerous. Andrei
Jun 07 2013
Am Fri, 07 Jun 2013 17:03:47 -0400 schrieb Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:On 6/7/13 4:52 PM, Mrzlga wrote:That made me scratch my head again. I thought std.traits contains non-modifying queries into the type system and std.typecons contains the _actions_ for type system trickery. In any case I wouldn't have searched std.traits for a function that gets stuff done. On the topic, I think that D's cast() does too many things in one. You can _accidentally_ cast away immutable for example and run into undefined behavior as per the language specs. At first I liked how D got rid of C's different casts, but on the long run it is too pragmatic for my taste. -- MarcoHi guys, This is a small feature proposal. Please consider to add these to the language: cast(signed) cast(unsigned)We should prolly add signed() as well. Could you please author an enhancement request (and at best a pull request too)? Thanks, Andrei
Jun 07 2013
On Friday, 7 June 2013 at 20:52:53 UTC, Mrzlga wrote:That's it! Thanks for your consideration :)FWI, you can use std.trait's Signed and Unsigned as a partial alternative. IMO, not quite as elegant. I support this syntax. It's natural, and I *think* the "keywords" are reserved anyways, so that shouldn't be a problem anyways. We already have "cast(const)" anyways, so cast(signed) is (imo) only natural. I'd almost expect it to work. I think this isn't the first time it has been brought up either. Unless I'm mistaken, user Bearophile has opened a request for this. Not 100% sure though. Gonna look for it.
Jun 07 2013
On Friday, 7 June 2013 at 21:04:40 UTC, monarch_dodra wrote:On Friday, 7 June 2013 at 20:52:53 UTC, Mrzlga wrote:EDIT: Couldn't find it. Must have been my imagination. Didn't realize we had "signed" too (as opposed to "Signed"), so I'm not sure how useful that would be actually. I still find it idiomatic though.That's it! Thanks for your consideration :)FWI, you can use std.trait's Signed and Unsigned as a partial alternative. IMO, not quite as elegant. I support this syntax. It's natural, and I *think* the "keywords" are reserved anyways, so that shouldn't be a problem anyways. We already have "cast(const)" anyways, so cast(signed) is (imo) only natural. I'd almost expect it to work. I think this isn't the first time it has been brought up either. Unless I'm mistaken, user Bearophile has opened a request for this. Not 100% sure though. Gonna look for it.
Jun 07 2013
On Friday, 7 June 2013 at 20:52:53 UTC, Mrzlga wrote:- Use the library for it and instead make signed(x), unsigned(x) templates.This !
Jun 08 2013