www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - using the full range of ubyte with iota

reply "Dominikus Dittes Scherkl" writes:
Maybe I'm just too stupid, but I cannot manage to call a simple 
function
with all 256 possible values of ubyte with iote:

int foo(ubyte c);

auto myRange = iota(0,256).map!foo;

-->  Error: function foo(ubyte c) is not callable using argument 
types (int)

and this is because of the f*** end-type cannot be ubyte because 
in phobos everywhere end is excluded, so I have to define it too 
large by one.

Has anyone any idea how to work around this?
I would have no problem using an explicit cast, but where should 
I apply it?
Jan 24 2015
next sibling parent reply "Tobias Pankrath" <tobias pankrath.net> writes:
On Saturday, 24 January 2015 at 20:49:03 UTC, Dominikus Dittes 
Scherkl wrote:
 Maybe I'm just too stupid, but I cannot manage to call a simple 
 function
 with all 256 possible values of ubyte with iote:

 int foo(ubyte c);

 auto myRange = iota(0,256).map!foo;

 -->  Error: function foo(ubyte c) is not callable using 
 argument types (int)

 and this is because of the f*** end-type cannot be ubyte 
 because in phobos everywhere end is excluded, so I have to 
 define it too large by one.

 Has anyone any idea how to work around this?
 I would have no problem using an explicit cast, but where 
 should I apply it?
iota(0, 256).map!(x => foo(cast(ubyte) x))
Jan 24 2015
parent reply "Dominikus Dittes Scherkl" writes:
On Saturday, 24 January 2015 at 21:00:06 UTC, Tobias Pankrath 
wrote:
 On Saturday, 24 January 2015 at 20:49:03 UTC, Dominikus Dittes 
 Scherkl wrote:
 I would have no problem using an explicit cast, but where 
 should I apply it?
iota(0, 256).map!(x => foo(cast(ubyte) x))
Ok, thank you very much. 4 times exactly the same answer - seems to be a common solution to a well known problem. :-/
Jan 24 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Sat, 24 Jan 2015 22:57:57 +0000, Dominikus Dittes Scherkl wrote:

 On Saturday, 24 January 2015 at 21:00:06 UTC, Tobias Pankrath wrote:
 On Saturday, 24 January 2015 at 20:49:03 UTC, Dominikus Dittes Scherkl
 wrote:
 I would have no problem using an explicit cast, but where should I
 apply it?
iota(0, 256).map!(x =3D> foo(cast(ubyte) x))
=20 Ok, thank you very much. =20 4 times exactly the same answer - seems to be a common solution to a well known problem. :-/
people that are new to D aren't used to D lambdas, so it's fairly common.=20 if you'll stay with D, you'll find yourself dreaming about such handy=20 thing in another compiled languages very soon. ;-)=
Jan 24 2015
parent reply "Dominikus Dittes Scherkl" writes:
On Saturday, 24 January 2015 at 23:19:11 UTC, ketmar wrote:
 people that are new to D aren't used to D lambdas, so it's 
 fairly common.
Oh, I am aware, but I didn't thought it would be necessary in this pace.
 if you'll stay with D, you'll find yourself dreaming about such 
 handy thing in another compiled languages very soon. ;-)
I don't consider to use any other language as long as I have a choice :-) But in the end, my one short and beautiful solution auto myRange = iota(start, end).map!foo; changed into something quite klumsy: auto myRange = iota(start, end).map!(x => foo(cast(ParameterTypeTuple!foo[0])x)); which I think is against the philosophy of D as it turns away the eye of the reader from what is really going on, especially if previous constraints ensured that start and end-1 are of the correct type :-( But ok, still far, far better than what would be neccessary in C++
Jan 24 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Sun, 25 Jan 2015 00:12:18 +0000, Dominikus Dittes Scherkl wrote:

 On Saturday, 24 January 2015 at 23:19:11 UTC, ketmar wrote:
 people that are new to D aren't used to D lambdas, so it's fairly
 common.
Oh, I am aware, but I didn't thought it would be necessary in this pace. =20
 if you'll stay with D, you'll find yourself dreaming about such handy
 thing in another compiled languages very soon. ;-)
=20 I don't consider to use any other language as long as I have a choice :-) =20 But in the end, my one short and beautiful solution =20 auto myRange =3D iota(start, end).map!foo; =20 changed into something quite klumsy: =20 auto myRange =3D iota(start, end).map!(x =3D> foo(cast(ParameterTypeTuple!foo[0])x)); =20 which I think is against the philosophy of D as it turns away the eye of the reader from what is really going on, especially if previous constraints ensured that start and end-1 are of the correct type :-( =20 But ok, still far, far better than what would be neccessary in C++
you can always write your own iota replacement, which will do "[]" and=20 use ubytes, for example. writing that things is way easier than in C++.=20 something like "myIota!ubyte(0, 255)", for example -- to make it visible=20 that it emits ubytes.=
Jan 24 2015
parent reply "Vlad Levenfeld" <vlevenfeld gmail.com> writes:
 you can always write your own iota replacement, which will do 
 "[]" and
 use ubytes, for example. writing that things is way easier than 
 in C++.
 something like "myIota!ubyte(0, 255)", for example -- to make 
 it visible
 that it emits ubytes.
I think closedInterval!T (T left, T right) would be a nice name for it. What's this about !`[]` and std.range.uniform?? It's not in the documentation.
Jan 24 2015
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Vlad Levenfeld:

 What's this about !`[]` and std.range.uniform?? It's not in the 
 documentation.
It's an enhancement I have proposed. Bye, bearophile
Jan 25 2015
parent reply "Dominikus Dittes Scherkl" writes:
On Sunday, 25 January 2015 at 10:42:51 UTC, bearophile wrote:
 Vlad Levenfeld:

 What's this about !`[]` and std.range.uniform?? It's not in 
 the documentation.
It's an enhancement I have proposed.
Hm. I had more something in mind like "paramCast" - a kind of big scissors that cut everything a function is called with to the size it can cope with, so replacing map!fn not with map!(x => fn(cast(ParameterTypeTuple!fn[0])x) but instead with map!(paramCast!fn) Because this is useful in more situations, e.g. in every place where you know the values would fit into the parameter (and for a single call would use a cast). But so far I couldn't manage to make this work :-/
Jan 25 2015
next sibling parent reply "Tobias Pankrath" <tobias pankrath.net> writes:
On Sunday, 25 January 2015 at 12:25:35 UTC, Dominikus Dittes 
Scherkl wrote:
 map!(x => fn(cast(ParameterTypeTuple!fn[0])x)

 but instead with

 map!(paramCast!fn)

 Because this is useful in more situations, e.g. in every place 
 where you know the values would fit into the parameter (and for 
 a single call would use a cast).

 But so far I couldn't manage to make this work :-/
http://dpaste.dzfl.pl/07b1fa3c2dad
Jan 25 2015
parent "Dominikus Dittes Scherkl" writes:
On Sunday, 25 January 2015 at 12:56:14 UTC, Tobias Pankrath wrote:
 On Sunday, 25 January 2015 at 12:25:35 UTC, Dominikus Dittes 
 Scherkl wrote:
 map!(x => fn(cast(ParameterTypeTuple!fn[0])x)

 but instead with

 map!(paramCast!fn)

 Because this is useful in more situations, e.g. in every place 
 where you know the values would fit into the parameter (and 
 for a single call would use a cast).

 But so far I couldn't manage to make this work :-/
http://dpaste.dzfl.pl/07b1fa3c2dad
Hey cool. With unary function I can even remove the string and mixin magic: template paramCast(alias fn) { ReturnType!fn paramCast(T)(T x) { return fn(cast(ParameterTypeTuple!fn[0])x); } } Many Thanks!
Jan 25 2015
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Dominikus Dittes Scherkl:

 Because this is useful in more situations,
Right, but it's still a cast. And in D you want to minimize the number of usages of casts. The proposed syntax iota!"[]" is cast-safe. Bye, bearophile
Jan 25 2015
parent reply "Dominikus Dittes Scherkl" writes:
On Sunday, 25 January 2015 at 13:03:16 UTC, bearophile wrote:
 Dominikus Dittes Scherkl:

 Because this is useful in more situations,
Right, but it's still a cast. And in D you want to minimize the number of usages of casts. The proposed syntax iota!"[]" is cast-safe.
I don't case too much, if I have ensured the cast is safe by constraints beforehand. I need to cast often anyway, because I work with small types and most operators permanently change everything to "int", especially the bit-operations for which a signed type makes no sense at all: ubyte x = 50; auto y = x & 0x11; // y is int! I hate that! even if I use unsigned literals: auto z = x & 0x12u; // z is uint - better but still bad. More so as & should result in the smaller of the two types!! But I need not even use literals (which unfortunately cannot be makred as "ubyte" or "short"). Look at this: auto x2 = (x>>4) | (x<<4); // swap nibbles - but result in an int!!!!!
Jan 25 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Sun, 25 Jan 2015 14:11:09 +0000, Dominikus Dittes Scherkl wrote:

 On Sunday, 25 January 2015 at 13:03:16 UTC, bearophile wrote:
 Dominikus Dittes Scherkl:

 Because this is useful in more situations,
Right, but it's still a cast. And in D you want to minimize the number of usages of casts. The proposed syntax iota!"[]" is cast-safe.
I don't case too much, if I have ensured the cast is safe by constraints beforehand. =20 I need to cast often anyway, because I work with small types and most operators permanently change everything to "int", especially the bit-operations for which a signed type makes no sense at all: =20 ubyte x =3D 50; auto y =3D x & 0x11; // y is int! I hate that! =20 even if I use unsigned literals: auto z =3D x & 0x12u; // z is uint - better but still bad. More so as & should result in the smaller of the two types!! =20 But I need not even use literals (which unfortunately cannot be makred as "ubyte" or "short"). Look at this: =20 auto x2 =3D (x>>4) | (x<<4); // swap nibbles - but result in an int!!!!!
this is true for C and C++ too, as all three languages doing "integer=20 promotion". the only difference is that D forbids potentially lossy=20 assigns. you best bet is to not use `auto`, but specify required type explicitly.=20 or use ints/uints and cast to bytes only when it is necessary.=
Jan 25 2015
parent reply "Dominikus Dittes Scherkl" writes:
On Sunday, 25 January 2015 at 18:59:04 UTC, ketmar wrote:
 auto x2 = (x>>4) | (x<<4); // swap nibbles - but result in an 
 int!!!!!
this is true for C and C++ too, as all three languages doing "integer promotion". the only difference is that D forbids potentially lossy assigns. you best bet is to not use `auto`, but specify required type explicitly. or use ints/uints and cast to bytes only when it is necessary.
in normal assignments I never use auto - it's not simpler than writing the type explicit but later makes it more complicated to see what type it is. But in a function you need the cast anyway: ubyte swapNibbles(ubyte x) { return (x>>4) | (x>>4); } // compiler not happy or if you index with a long, even after explicit check: int foo(ulong x) { int[10] a; return (x < 10) ? a[x] : 0; // cannot index with long } So there are plenty of places in D where cast is necessary but should not be. I think both of above cases should be safe without cast, and enhancing the compilerr that it can handle these cases is more important than a iota!"[]". Until then I prefer paramCast!fn, because this is more flexible than the iota extension and my code is full of casts anyway.
Jan 25 2015
parent ketmar <ketmar ketmar.no-ip.org> writes:
On Sun, 25 Jan 2015 20:42:47 +0000, Dominikus Dittes Scherkl wrote:

 But in a function you need the cast anyway:
 ubyte swapNibbles(ubyte x) { return (x>>4) | (x>>4); } // compiler not
 happy
sure, it can't be happy, as `x` is promoted to int in the expression, so=20 the expression result is `int`. better range analysis can prove that the=20 resuit can be fit in `ubyte`, of course. or you can do `&0xff` -- the=20 compiler is intelligent enough to see that this fits to ubyte too.
 or if you index with a long, even after explicit check:
=20
 int foo(ulong x)
 {
     int[10] a;
     return (x < 10) ? a[x] : 0; // cannot index with long
 }
why do you index with `ulong`s in the first place? there is ugly `size_t`=20 type for this. anyway, what you talking about is a missing integer range analysis in=20 complier. i'm not sure that it worth adding, as it slows down compilation=20 and hiding some potentially bad code. i can grep for `cast`s to see where=20 author is playing with fire, but i can't grep for range analysis. ;-) p.s. `a[x&size_t.max]` works fine in your sample. and to be honest, i=20 prefer either this, or `cast` -- any form of explicit type transformation. p.p.s. what is bad is that compiler happily accepts this: int foo (int x) { int[10] a; return a[x]; } WTF?! why, in the name of Ruler of Hell, array indexing with int doesn't=20 generate any warning?! D design decision to silently allow conversion of=20 `int` to `uint`/`ulong` is conceptually flawed. but this is one of the=20 things that will never be fixed, so we have to live with it.=
Jan 25 2015
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Dominikus Dittes Scherkl:

 Has anyone any idea how to work around this?
In Bugzilla I have proposed to solve this problem with this syntax taken from std.range.uniform: iota!"[]"(ubyte.min, ubyte.max) Bye, bearophile
Jan 24 2015
prev sibling next sibling parent "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Sat, Jan 24, 2015 at 08:49:01PM +0000, Dominikus Dittes Scherkl via
Digitalmars-d-learn wrote:
 Maybe I'm just too stupid, but I cannot manage to call a simple function
 with all 256 possible values of ubyte with iote:
 
 int foo(ubyte c);
 
 auto myRange = iota(0,256).map!foo;
[...] Try: auto myRange = iota(0, 256).map!(a => foo(cast(ubyte)a)); T -- Shin: (n.) A device for finding furniture in the dark.
Jan 24 2015
prev sibling next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
On Sat, 24 Jan 2015 20:49:01 +0000, Dominikus Dittes Scherkl wrote:

 Maybe I'm just too stupid, but I cannot manage to call a simple function
 with all 256 possible values of ubyte with iote:
=20
 int foo(ubyte c);
=20
 auto myRange =3D iota(0,256).map!foo;
=20
 -->  Error: function foo(ubyte c) is not callable using argument types
 (int)
=20
 and this is because of the f*** end-type cannot be ubyte because in
 phobos everywhere end is excluded, so I have to define it too large by
 one.
=20
 Has anyone any idea how to work around this?
 I would have no problem using an explicit cast, but where should I apply
 it?
auto myRange =3D iota(0, 256).map!(a =3D> foo(cast(ubyte)a)); =
Jan 24 2015
prev sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
juicy question!=
Jan 24 2015