digitalmars.D.learn - Why do I have to cast arguments from int to byte?
- Chirs Forest (19/19) Oct 10 2017 I keep having to make casts like the following and it's really
- Moritz Maxeiner (3/9) Oct 10 2017 Because of integer promotion [1], which is inherited from C.
- Igor Shirkalin (2/21) Oct 10 2017 Because int (1) + ubyte (9) = int
- Adam D. Ruppe (8/9) Oct 10 2017 D inherited a silly rule from C where any arithmetic is promoted
- rjframe (16/30) Oct 10 2017 You could wrap the cast in a function to clean it up a bit:
- Daniel Kozak (10/28) Oct 11 2017 You can avoid cast:
- kdevel (14/18) Oct 12 2017 Sure?
- Daniel Kozak (3/25) Oct 13 2017 Not sure :), I have forgoten byte+byte=int.
- Daniel Kozak (5/35) Oct 13 2017 but it works ok with immutable, so until you really need to change bar y...
- kdevel (6/10) Oct 13 2017 As Adam wrote two days ago: 'D doesn't do implicit narrowing
- Steven Schveighoffer (9/19) Oct 13 2017 Right, the reason why your original didn't work is the compiler
I keep having to make casts like the following and it's really rubbing me the wrong way: void foo(T)(T bar){...} byte bar = 9; foo!byte(bar + 1); //Error: function foo!byte.foo (byte bar) is not callable using argument types (int) foo!byte(cast(byte)(bar + 1)); It wouldn't be so bad if I didn't have to use the word cast before each cast, bust since I have to specify both the word cast and the cast type and then wrap both the cast type and the value in brackets... it just explodes my code into multiple lines of unreadable mess. void foo(T)(T bar, T bar2, T bar3){...} byte foobar = 12; foo!byte(foobar + 1, foobar + 22, foobar + 333); vs. foo!byte(cast(byte)(foobar + 1), cast(byte)(foobar + 22), cast(byte)(foobar + 333)); Why?
Oct 10 2017
On Tuesday, 10 October 2017 at 19:55:36 UTC, Chirs Forest wrote:I keep having to make casts like the following and it's really rubbing me the wrong way: void foo(T)(T bar){...} byte bar = 9; [...] Why?Because of integer promotion [1], which is inherited from C. [1] https://dlang.org/spec/type.html#integer-promotions
Oct 10 2017
On Tuesday, 10 October 2017 at 19:55:36 UTC, Chirs Forest wrote:I keep having to make casts like the following and it's really rubbing me the wrong way: void foo(T)(T bar){...} byte bar = 9; foo!byte(bar + 1); //Error: function foo!byte.foo (byte bar) is not callable using argument types (int) foo!byte(cast(byte)(bar + 1)); It wouldn't be so bad if I didn't have to use the word cast before each cast, bust since I have to specify both the word cast and the cast type and then wrap both the cast type and the value in brackets... it just explodes my code into multiple lines of unreadable mess. void foo(T)(T bar, T bar2, T bar3){...} byte foobar = 12; foo!byte(foobar + 1, foobar + 22, foobar + 333); vs. foo!byte(cast(byte)(foobar + 1), cast(byte)(foobar + 22), cast(byte)(foobar + 333)); Why?Because int (1) + ubyte (9) = int
Oct 10 2017
On Tuesday, 10 October 2017 at 19:55:36 UTC, Chirs Forest wrote:Why?D inherited a silly rule from C where any arithmetic is promoted to int first. The big difference is D doesn't do implicit narrowing conversion... so x + 1 becomes int, but then int to byte requires an explicit cast (unless the compiler can prove the range in that particular expression - this is called "value range propagation"). I think it has proved to be a bit of a mistake :(
Oct 10 2017
On Tue, 10 Oct 2017 19:55:36 +0000, Chirs Forest wrote:It wouldn't be so bad if I didn't have to use the word cast before each cast, bust since I have to specify both the word cast and the cast type and then wrap both the cast type and the value in brackets... it just explodes my code into multiple lines of unreadable mess. void foo(T)(T bar, T bar2, T bar3){...} byte foobar = 12; foo!byte(foobar + 1, foobar + 22, foobar + 333); vs. foo!byte(cast(byte)(foobar + 1), cast(byte)(foobar + 22), cast(byte)(foobar + 333));You could wrap the cast in a function to clean it up a bit: void main() { byte foobar = 12; foo!byte((foobar + 1).b, (foobar + 22).b, (foobar + 333).b); } byte b(int n) pure { pragma(inline, true); // Probably not necessary. return cast(byte)n; } void foo(T)(T bar, T bar2, T bar3) { import std.stdio : writeln; import std.string : format; writeln("%s, %s, %s".format(bar, bar2, bar3)); } --Ryan
Oct 10 2017
You can avoid cast: void foo(T)(T bar){...} byte bar = 9; foo!byte(bar + byte(1)); or byte bar = 9; byte num = 1; foo!byte(bar + num); On Tue, Oct 10, 2017 at 9:55 PM, Chirs Forest via Digitalmars-d-learn < digitalmars-d-learn puremagic.com> wrote:I keep having to make casts like the following and it's really rubbing me the wrong way: void foo(T)(T bar){...} byte bar = 9; foo!byte(bar + 1); //Error: function foo!byte.foo (byte bar) is not callable using argument types (int) foo!byte(cast(byte)(bar + 1)); It wouldn't be so bad if I didn't have to use the word cast before each cast, bust since I have to specify both the word cast and the cast type and then wrap both the cast type and the value in brackets... it just explodes my code into multiple lines of unreadable mess. void foo(T)(T bar, T bar2, T bar3){...} byte foobar = 12; foo!byte(foobar + 1, foobar + 22, foobar + 333); vs. foo!byte(cast(byte)(foobar + 1), cast(byte)(foobar + 22), cast(byte)(foobar + 333)); Why?
Oct 11 2017
On Wednesday, 11 October 2017 at 07:09:26 UTC, Daniel Kozak wrote:You can avoid cast: void foo(T)(T bar){...} byte bar = 9; foo!byte(bar + byte(1));Sure? --- void foo(T)(T bar) { } byte bar = 9; void main () { foo!byte(bar + byte(1)); } --- byte2.d(7): Error: function byte2.foo!byte.foo (byte bar) is not callable using argument types (int)
Oct 12 2017
Not sure :), I have forgoten byte+byte=int. On Thu, Oct 12, 2017 at 10:51 PM, kdevel via Digitalmars-d-learn < digitalmars-d-learn puremagic.com> wrote:On Wednesday, 11 October 2017 at 07:09:26 UTC, Daniel Kozak wrote:You can avoid cast: void foo(T)(T bar){...} byte bar = 9; foo!byte(bar + byte(1));Sure? --- void foo(T)(T bar) { } byte bar = 9; void main () { foo!byte(bar + byte(1)); } --- byte2.d(7): Error: function byte2.foo!byte.foo (byte bar) is not callable using argument types (int)
Oct 13 2017
but it works ok with immutable, so until you really need to change bar you can use immutable bar = 9; foo!byte(bar + 1); On Fri, Oct 13, 2017 at 9:46 AM, Daniel Kozak <kozzi11 gmail.com> wrote:Not sure :), I have forgoten byte+byte=int. On Thu, Oct 12, 2017 at 10:51 PM, kdevel via Digitalmars-d-learn < digitalmars-d-learn puremagic.com> wrote:On Wednesday, 11 October 2017 at 07:09:26 UTC, Daniel Kozak wrote:You can avoid cast: void foo(T)(T bar){...} byte bar = 9; foo!byte(bar + byte(1));Sure? --- void foo(T)(T bar) { } byte bar = 9; void main () { foo!byte(bar + byte(1)); } --- byte2.d(7): Error: function byte2.foo!byte.foo (byte bar) is not callable using argument types (int)
Oct 13 2017
On Friday, 13 October 2017 at 07:47:55 UTC, Daniel Kozak wrote:but it works ok with immutable, so until you really need to change bar you can use immutable bar = 9; foo!byte(bar + 1);As Adam wrote two days ago: 'D doesn't do implicit narrowing conversion... so x + 1 becomes int, but then int to byte requires an explicit cast (unless the compiler can prove the range in that particular expression - this is called "value range propagation").'
Oct 13 2017
On 10/13/17 3:47 AM, Daniel Kozak wrote:but it works ok with immutable, so until you really need to change bar you can use immutable bar = 9; foo!byte(bar + 1);Right, the reason why your original didn't work is the compiler "forgets" that bar is 9 by the time it gets to the foo call. However, it doesn't forget the value of an immutable.On Fri, Oct 13, 2017 at 9:46 AM, Daniel Kozak <kozzi11 gmail.com <mailto:kozzi11 gmail.com>> wrote: Not sure :), I have forgoten byte+byte=int.One place where the compiler doesn't care is +=: bar += 400; // OK int y = 400; bar += y; // OK -Steve
Oct 13 2017