www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Why no cast between integral types and bit[]?

reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
This works just fine:

ubyte[] a=new ubyte[1];
a[0]=5;
bit[] b=cast(bit[])a;

But this doesn't:

ubyte a=5;
bit[] b=cast(bit[])a;

I would think that adding support of casting integral types to bit arrays 
would be a trivial task, as it would be just like casting a single-element 
array.

Then there's the inverse:

static bit[8] b=[1,0,1,0,0,0,0,0];
ubyte[] a=cast(ubyte[])b;
writefln(a);

I can see how casting from bit[] to an integral type would be a little more 
difficult, but really, all that'd have to be done would be to increase the 
length of the bit array to the size of the integer if it's too small.

How about it? 
Aug 19 2005
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
news:de4rek$27i9$1 digitaldaemon.com...
 This works just fine:

 ubyte[] a=new ubyte[1];
 a[0]=5;
 bit[] b=cast(bit[])a;

 But this doesn't:

 ubyte a=5;
 bit[] b=cast(bit[])a;

 I would think that adding support of casting integral types to bit arrays 
 would be a trivial task, as it would be just like casting a single-element 
 array.

What would cast(bit[])(1+2) do?
 Then there's the inverse:

 static bit[8] b=[1,0,1,0,0,0,0,0];
 ubyte[] a=cast(ubyte[])b;
 writefln(a);

 I can see how casting from bit[] to an integral type would be a little 
 more difficult, but really, all that'd have to be done would be to 
 increase the length of the bit array to the size of the integer if it's 
 too small.

 How about it?
 

Aug 19 2005
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Ben Hinkle" <bhinkle mathworks.com> wrote in message 
news:de4usa$2bas$1 digitaldaemon.com...
 What would cast(bit[])(1+2) do?

Return a bit array 32 elements long with bits 0 and 1 set to 1?
Aug 19 2005
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
news:de578c$2iq7$1 digitaldaemon.com...
 "Ben Hinkle" <bhinkle mathworks.com> wrote in message 
 news:de4usa$2bas$1 digitaldaemon.com...
 What would cast(bit[])(1+2) do?

Return a bit array 32 elements long with bits 0 and 1 set to 1?

But a dynamic array is a pointer and length so I don't know where it is getting the pointer from. I know bit[] is funny sometimes wrt array semantics but it needs a ptr.
Aug 19 2005
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Ben Hinkle" <bhinkle mathworks.com> wrote in message 
news:de58t4$2k80$1 digitaldaemon.com...
 But a dynamic array is a pointer and length so I don't know where it is 
 getting the pointer from. I know bit[] is funny sometimes wrt array 
 semantics but it needs a ptr.

..You know, that's a good point. Then again, nothing says that the result of a cast has to point to the location of the expression that was casted, so a cast to a bit array could return a new bit array. But if you really wanted the cast to point to the original number, the D compiler could force it to, doing something like: bit[]* intToBit(int* x) { struct arr { uint length; void* ptr; } arr* a=new arr; a.length=32; a.ptr=x; return cast(bit[]*)cast(void*)a; } void main() { int x=5; bit[] b=*intToBit(&x); // Writes 00000000000000000000000000000101 for(int i=31; i>=0; i--) writef(b[i] ? 1 : 0); } Of course, since the compiler has access to all the internals of the arrays, it wouldn't have to use a kludgy function like that.
Aug 19 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
news:de5lla$2uci$1 digitaldaemon.com...
 "Ben Hinkle" <bhinkle mathworks.com> wrote in message 
 news:de58t4$2k80$1 digitaldaemon.com...
 But a dynamic array is a pointer and length so I don't know where it is 
 getting the pointer from. I know bit[] is funny sometimes wrt array 
 semantics but it needs a ptr.

..You know, that's a good point. Then again, nothing says that the result of a cast has to point to the location of the expression that was casted,

Not all expression evaluate to lvalues. For example there is no location of the result of the expression (1+2). You can't say &(1+2).
 so a cast to a bit array could return a new bit array.  But if you really 
 wanted the cast to point to the original number, the D compiler could 
 force it to, doing something like:

 bit[]* intToBit(int* x)
 {
    struct arr
    {
        uint length;
        void* ptr;
    }

    arr* a=new arr;
    a.length=32;
    a.ptr=x;
    return cast(bit[]*)cast(void*)a;
 }

I'm not sure why you are allocating a new dynamic array reference from the GC. One can write intToBit as bit[] toBits(void* x, int len) { return cast(bit[])x[0..len]; } int main() { int x; bit[] b = toBits(&x,x.sizeof*8); b[3] = 1; printf("%d\n",x); return 0; } In any case one still has to supply a pointer to x. I think making more special cases for bit arrays is not worth it especially when a little helper like toBits can make the code more readable if that's the concern.
 void main()
 {
    int x=5;
    bit[] b=*intToBit(&x);

    // Writes 00000000000000000000000000000101
    for(int i=31; i>=0; i--)
        writef(b[i] ? 1 : 0);
 }

 Of course, since the compiler has access to all the internals of the 
 arrays, it wouldn't have to use a kludgy function like that.
 

Aug 19 2005
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Ben Hinkle" <ben.hinkle gmail.com> wrote in message 
news:de5pf8$3168$1 digitaldaemon.com...
 Not all expression evaluate to lvalues. For example there is no location 
 of the result of the expression (1+2). You can't say &(1+2).

You also can't say 5=x, but that didn't seem to be what you were getting at with your first reply.
 I'm not sure why you are allocating a new dynamic array reference from the 
 GC. One can write intToBit as

 bit[] toBits(void* x, int len) {
  return cast(bit[])x[0..len];
 }

 int main() {
  int x;
  bit[] b = toBits(&x,x.sizeof*8);
  b[3] = 1;
  printf("%d\n",x);
  return 0;
 }

I wasn't aware that you could cast void[] to bit[], as I had tried casting void* to bit[] and it didn't seem to work; hence the bit[]* thing in mine.
 In any case one still has to supply a pointer to x. I think making more 
 special cases for bit arrays is not worth it especially when a little 
 helper like toBits can make the code more readable if that's the concern.

Oh, have it your way then ;) I just always thought that it was odd that D supported arrays of consecutive bits, while it had no support for converting integers, which are consecutive arrays of bits, to bit arrays.
Aug 19 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
I've often thought that the ability to slice any basic type would be quite  
nice, eg.

ubyte b;
uint i;
long l;

b[0] = 1;
i[5] = 0;
l[16..32] = 1;

in other words slicing a basic type gives a bit[] or bit.

Of course the big problem that rears it's head is how does this work:

bit[] b;
uint i;

b = i[5..15];

A slice on non-byte boundaries... It seems it can't without copying or  
great internal hoop jumping. So, I would limit the feature to lvalue  
assignments instead, i.e.

bit[10] b;
uint i;

i[5..15] = b[]; //would be fine, but
b = i[5..15]; //would not

perhaps, if we desire, we can allow:

b[] = i[5..15];

or

b = i[5..15].dup;

i.e. a copy would be easier to implement.

The reason I like this is that code that would read something like:

variable |= 1<<16;

or

variable &= ~(1<<16)

or whatever can now read:

variable[16] = 1;

or

variable[16] = 0;

(note I have not paid strict attention to the code above, it's probably  
wrong, but you should get the picture)

Regan
Aug 19 2005
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Regan Heath" <regan netwin.co.nz> wrote in message 
news:opsvr9dkx523k2f5 nrage.netwin.co.nz...
 I've often thought that the ability to slice any basic type would be quite 
 nice, eg.

 ubyte b;
 uint i;
 long l;

 b[0] = 1;
 i[5] = 0;
 l[16..32] = 1;

 in other words slicing a basic type gives a bit[] or bit.

 Of course the big problem that rears it's head is how does this work:

 bit[] b;
 uint i;

 b = i[5..15];

 A slice on non-byte boundaries... It seems it can't without copying or 
 great internal hoop jumping. So, I would limit the feature to lvalue 
 assignments instead, i.e.

 bit[10] b;
 uint i;

 i[5..15] = b[]; //would be fine, but
 b = i[5..15]; //would not

 perhaps, if we desire, we can allow:

 b[] = i[5..15];

 or

 b = i[5..15].dup;

 i.e. a copy would be easier to implement.

 The reason I like this is that code that would read something like:

 variable |= 1<<16;

 or

 variable &= ~(1<<16)

 or whatever can now read:

 variable[16] = 1;

 or

 variable[16] = 0;

 (note I have not paid strict attention to the code above, it's probably 
 wrong, but you should get the picture)

 Regan

Right, that's kind of what I would like this for, twiddling bits in numbers. I was thinking about something to replace bitfields as well, as shifting and masking is just so much fun, but it'd be nice to do something like a[0..4]=6. Then again, for bitfields, you could use a union between a bit[32] and a uint.
Aug 20 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
news:de7c77$17at$1 digitaldaemon.com...
 "Regan Heath" <regan netwin.co.nz> wrote in message 
 news:opsvr9dkx523k2f5 nrage.netwin.co.nz...
 I've often thought that the ability to slice any basic type would be 
 quite nice, eg.

 ubyte b;
 uint i;
 long l;

 b[0] = 1;
 i[5] = 0;
 l[16..32] = 1;

 in other words slicing a basic type gives a bit[] or bit.

 Of course the big problem that rears it's head is how does this work:

 bit[] b;
 uint i;

 b = i[5..15];

 A slice on non-byte boundaries... It seems it can't without copying or 
 great internal hoop jumping. So, I would limit the feature to lvalue 
 assignments instead, i.e.

 bit[10] b;
 uint i;

 i[5..15] = b[]; //would be fine, but
 b = i[5..15]; //would not

 perhaps, if we desire, we can allow:

 b[] = i[5..15];

 or

 b = i[5..15].dup;

 i.e. a copy would be easier to implement.

 The reason I like this is that code that would read something like:

 variable |= 1<<16;

 or

 variable &= ~(1<<16)

 or whatever can now read:

 variable[16] = 1;

 or

 variable[16] = 0;

 (note I have not paid strict attention to the code above, it's probably 
 wrong, but you should get the picture)

 Regan

Right, that's kind of what I would like this for, twiddling bits in numbers. I was thinking about something to replace bitfields as well, as shifting and masking is just so much fun, but it'd be nice to do something like a[0..4]=6. Then again, for bitfields, you could use a union between a bit[32] and a uint.

The thing about a bit array is that it doesn't know about big-endian or little-endian and the exact packing of the bit array into memory is compiler-dependent (see for example http://www.digitalmars.com/d/arrays.html#bitarrays). With shifting the compiler knows the size of the data being shifted and so you the coder don't have to worry about all the memory layout details.
Aug 20 2005
next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Ben Hinkle" <ben.hinkle gmail.com> wrote in message 
news:de7enn$1998$1 digitaldaemon.com...
 The thing about a bit array is that it doesn't know about big-endian or 
 little-endian and the exact packing of the bit array into memory is 
 compiler-dependent (see for example 
 http://www.digitalmars.com/d/arrays.html#bitarrays). With shifting the 
 compiler knows the size of the data being shifted and so you the coder 
 don't have to worry about all the memory layout details.

Oof. Yeah, that's an issue.
Aug 20 2005
prev sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Sat, 20 Aug 2005 10:28:33 -0400, Ben Hinkle <ben.hinkle gmail.com>  
wrote:
 "Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message
 news:de7c77$17at$1 digitaldaemon.com...
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsvr9dkx523k2f5 nrage.netwin.co.nz...
 I've often thought that the ability to slice any basic type would be
 quite nice, eg.

 ubyte b;
 uint i;
 long l;

 b[0] = 1;
 i[5] = 0;
 l[16..32] = 1;

 in other words slicing a basic type gives a bit[] or bit.

 Of course the big problem that rears it's head is how does this work:

 bit[] b;
 uint i;

 b = i[5..15];

 A slice on non-byte boundaries... It seems it can't without copying or
 great internal hoop jumping. So, I would limit the feature to lvalue
 assignments instead, i.e.

 bit[10] b;
 uint i;

 i[5..15] = b[]; //would be fine, but
 b = i[5..15]; //would not

 perhaps, if we desire, we can allow:

 b[] = i[5..15];

 or

 b = i[5..15].dup;

 i.e. a copy would be easier to implement.

 The reason I like this is that code that would read something like:

 variable |= 1<<16;

 or

 variable &= ~(1<<16)

 or whatever can now read:

 variable[16] = 1;

 or

 variable[16] = 0;

 (note I have not paid strict attention to the code above, it's probably
 wrong, but you should get the picture)

 Regan

Right, that's kind of what I would like this for, twiddling bits in numbers. I was thinking about something to replace bitfields as well, as shifting and masking is just so much fun, but it'd be nice to do something like a[0..4]=6. Then again, for bitfields, you could use a union between a bit[32] and a uint.

The thing about a bit array is that it doesn't know about big-endian or little-endian and the exact packing of the bit array into memory is compiler-dependent (see for example http://www.digitalmars.com/d/arrays.html#bitarrays). With shifting the compiler knows the size of the data being shifted and so you the coder don't have to worry about all the memory layout details.

All the more reason to have the ability to slice basic types built-in and have the compiler work it's magic in the background. Regan
Aug 20 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"Regan Heath" <regan netwin.co.nz> wrote in message 
news:opsvtzskgc23k2f5 nrage.netwin.co.nz...
 On Sat, 20 Aug 2005 10:28:33 -0400, Ben Hinkle <ben.hinkle gmail.com> 
 wrote:
 "Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message
 news:de7c77$17at$1 digitaldaemon.com...
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:opsvr9dkx523k2f5 nrage.netwin.co.nz...
 I've often thought that the ability to slice any basic type would be
 quite nice, eg.

 ubyte b;
 uint i;
 long l;

 b[0] = 1;
 i[5] = 0;
 l[16..32] = 1;

 in other words slicing a basic type gives a bit[] or bit.

 Of course the big problem that rears it's head is how does this work:

 bit[] b;
 uint i;

 b = i[5..15];

 A slice on non-byte boundaries... It seems it can't without copying or
 great internal hoop jumping. So, I would limit the feature to lvalue
 assignments instead, i.e.

 bit[10] b;
 uint i;

 i[5..15] = b[]; //would be fine, but
 b = i[5..15]; //would not

 perhaps, if we desire, we can allow:

 b[] = i[5..15];

 or

 b = i[5..15].dup;

 i.e. a copy would be easier to implement.

 The reason I like this is that code that would read something like:

 variable |= 1<<16;

 or

 variable &= ~(1<<16)

 or whatever can now read:

 variable[16] = 1;

 or

 variable[16] = 0;

 (note I have not paid strict attention to the code above, it's probably
 wrong, but you should get the picture)

 Regan

Right, that's kind of what I would like this for, twiddling bits in numbers. I was thinking about something to replace bitfields as well, as shifting and masking is just so much fun, but it'd be nice to do something like a[0..4]=6. Then again, for bitfields, you could use a union between a bit[32] and a uint.

The thing about a bit array is that it doesn't know about big-endian or little-endian and the exact packing of the bit array into memory is compiler-dependent (see for example http://www.digitalmars.com/d/arrays.html#bitarrays). With shifting the compiler knows the size of the data being shifted and so you the coder don't have to worry about all the memory layout details.

All the more reason to have the ability to slice basic types built-in and have the compiler work it's magic in the background. Regan

I don't think the problems can be wished away with magic. The core issue is that bit[] forgets the layout of the numeric types. What would the expression x[a .. b] actually return? I don't mean "it returns the bits from a to b". I mean what is the type of the result? It should't be bit[]. It's simpler (and well-defined) to use & and |. Besides to me x[a .. b] is array indexing not bit-twiddling so I'm not even sure I like the idea of abusing [] to slice numeric types.
Aug 21 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Sun, 21 Aug 2005 10:05:46 -0400, Ben Hinkle <ben.hinkle gmail.com>  
wrote:
 All the more reason to have the ability to slice basic types built-in  
 and have the compiler work it's magic in the background.

I don't think the problems can be wished away with magic. The core issue is that bit[] forgets the layout of the numeric types. What would the expression x[a .. b] actually return? I don't mean "it returns the bits from a to b". I mean what is the type of the result?

Almost irrelevant. eg. in an assignment: uint b; b[0..5] = 1; It doesn't matter, the compiler is doing it all in the background, the user never needs to know the type, or have one to store anything in, however.. (see next response)
 It should't be bit[].

Why not? I mean, if you actually want to copy bits, you might write: bit[5] a; uint b; a[] = b[0..5]; I don't think we need/want to remove the bit[] types I just think being able to slice basic types to get bit[] types would be very useful. I think we do want to restrict it to bit boundaries or require a copy (anything else seems quite complicated, though the compiler is the best place to handle that, if it was desired)
 It's simpler

I disagree. After years of experience using & and | is easy (perhaps 'simple'), but, to a begginer it's not at all.
 (and well-defined) to use & and |.

In C and other languages, yes. In D, c'mon we have bit[], surely it can make bit twiddling really nice and easy. It seems bizarre to say the least that we're not using bit[] for bit twiddling but instead using old techniques which are both harder to understand and use (until you're proficient with them).
 Besides to me x[a .. b] is array indexing not bit-twiddling

Sure, until you add "= 1" or "= 0", then it's an assignment and thus bit twiddling .. obviously?
 so I'm not even sure I like the idea of
 abusing [] to slice numeric types.

"abusing" .. your opinion is obvious from your choice of words ;) IMO the idea of slicing a basic type to get bit[]: - Makes bit twiddling _much_ easier. - Makes bit twiddling _much_ simpler for begginers. - Makes more use of the bit[] type (we're not using it for bit twiddling, why?). Regan
Aug 21 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"Regan Heath" <regan netwin.co.nz> wrote in message 
news:opsvvmcao123k2f5 nrage.netwin.co.nz...
 On Sun, 21 Aug 2005 10:05:46 -0400, Ben Hinkle <ben.hinkle gmail.com> 
 wrote:
 All the more reason to have the ability to slice basic types built-in 
 and have the compiler work it's magic in the background.

I don't think the problems can be wished away with magic. The core issue is that bit[] forgets the layout of the numeric types. What would the expression x[a .. b] actually return? I don't mean "it returns the bits from a to b". I mean what is the type of the result?

Almost irrelevant. eg. in an assignment: uint b; b[0..5] = 1; It doesn't matter, the compiler is doing it all in the background, the user never needs to know the type, or have one to store anything in, however.. (see next response)

I thought you guys were looking for something general purpose. I agree if the proposal is limited to indexed assignment statements that the return type doesn't matter because there is no return type. But that's not what the proposal is, I thought.
 It should't be bit[].

Why not?

See http://en.wikipedia.org/wiki/Endian. On big-endian machines b[0..16], for example, would be the last two bytes of the memory range &b .. &b+4 in reverse order and for little endian machines is the first two bytes in incresing order. For longs and shorts it would behave similarly. The type bit[] is packed into compiler-dependent chunks in whatever ways it wants. I imagine it would take some non-trivial changes to bit[] to support slicing non-int sized types on big-endian machines.
 I mean, if you actually want to copy bits, you might write:

 bit[5] a;
 uint b;

 a[] = b[0..5];

I understand.
 I don't think we need/want to remove the bit[] types I just think being 
 able to slice basic types to get bit[] types would be very useful.

I'm not aware of any post in this thread suggesting bit[] go away. I'm aware you think slicing basic types to get bit[] would be useful.
 I think  we do want to restrict it to bit boundaries or require a copy 
 (anything  else seems quite complicated, though the compiler is the best 
 place to  handle that, if it was desired)

I'm not sure what exactly you are referring to. Which bit boundaries and copying do you mean? By the way, I'm guessing as to exactly what the proposal is. My impression is that the proposal is to slice lvalues of numeric type to obtain bit[]. The only numeric type I can imagine it working for is the underlying numeric type used by bit[] (on big endian machines). For little endian machines bit[] can be used for any slice that starts at a multiple of the underlying bit-packing unit (eg int).
 It's simpler

I disagree. After years of experience using & and | is easy (perhaps 'simple'), but, to a begginer it's not at all.

Given that using bit[] will require lots of special cases to explain (see above) I think & and | is simpler. If that's too confusing for beginners one can write simple functions like template getbit(T) bit getbit(T x, int n){ return cast(bit)(x & ((cast(T)1) << n)); } } etc
 (and well-defined) to use & and |.

In C and other languages, yes. In D, c'mon we have bit[], surely it can make bit twiddling really nice and easy. It seems bizarre to say the least that we're not using bit[] for bit twiddling but instead using old techniques which are both harder to understand and use (until you're proficient with them).

I think a more detailed proposal would help show the trade-off and true impact of trying to extend bit[] to be used as a replacement for &|. I don't think it's a trivial as you assume. I view bit[] as only being a packed array of true/false values (ala Pascal and C++). The exact packing behavior is compiler-dependent.
 Besides to me x[a .. b] is array indexing not bit-twiddling

Sure, until you add "= 1" or "= 0", then it's an assignment and thus bit twiddling .. obviously?
 so I'm not even sure I like the idea of
 abusing [] to slice numeric types.

"abusing" .. your opinion is obvious from your choice of words ;) IMO the idea of slicing a basic type to get bit[]: - Makes bit twiddling _much_ easier. - Makes bit twiddling _much_ simpler for begginers. - Makes more use of the bit[] type (we're not using it for bit twiddling, why?). Regan

Other languages have bit arrays - I'm thinking specifically of Pascal's packed arrays and STL's bit vectors but there could be others, too. I'm not aware of any that try to use bit arrays to do bit twiddling. They are meant to be memory efficient arrays of true/false values and that's it.
Aug 21 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Sun, 21 Aug 2005 19:22:54 -0400, Ben Hinkle <ben.hinkle gmail.com>  
wrote:
 It doesn't matter, the compiler is doing it all in the background, the
 user never needs to know the type, or have one to store anything in,
 however.. (see next response)

I thought you guys were looking for something general purpose.

The OP might have been. I wasn't.
 I agree if
 the proposal is limited to indexed assignment statements that the return
 type doesn't matter because there is no return type.

My proposal was 'limited' to it, with some exceptions i.e. allowing copying.
 See http://en.wikipedia.org/wiki/Endian. On big-endian machines b[0..16],
 for example, would be the last two bytes of the memory range &b .. &b+4  
 in
 reverse order and for little endian machines is the first two bytes in
 incresing order. For longs and shorts it would behave similarly.

I understand big/little endian. I don't understand why it's a problem. Either: 1 - the compiler handles the big/little endian nature of the bits for us, guaranteeing a certain ordering 2 - the compiler does nothing and we have to handle/understand it ourselves. If #1 it makes bit twiddling very simple to use and understand, don't you think? If #2 and the feature is limited to assignment and copying then (see my next response)
 The type bit[] is packed into compiler-dependent chunks in whatever ways  
 it wants. I imagine it would take some non-trivial changes to bit[] to  
 support slicing non-int sized types on big-endian machines.

I understand, I think. However, if it's restricted to assignments and copying it simplifies things a bit, the compiler already has to know how to access the bits, all that is added is the ability to set them or copy them. I'm saying, slicing without copying or assigning is not allowed, thus the bit[] type does not need to handle the packing of the bits. Instead on assignment the compiler handles it by assigning to them as it finds them. When copying it makes new data, copying from the old data and no changes are required to bit[] to handle this case.
 I think  we do want to restrict it to bit boundaries or require a copy
 (anything  else seems quite complicated, though the compiler is the best
 place to  handle that, if it was desired)

I'm not sure what exactly you are referring to. Which bit boundaries and copying do you mean?

Replace "bit" with "byte" above. I mean: uint a; bit[] b = a[2..12]; would not be possible because the slice crosses a byte boundary. but, a copy or assignment would be fine (reasons above) eg. uint a; bit[] b; b[] = a[2..12]; a[2..12] = 1;
 By the way, I'm guessing as to exactly what the
 proposal is. My impression is that the proposal is to slice lvalues of
 numeric type to obtain bit[].

Correct.
 The only numeric type I can imagine it working for is the underlying  
 numeric type used by bit[] (on big endian machines). For little endian  
 machines bit[] can be used for any slice that starts at a multiple of  
 the underlying bit-packing unit (eg int).

This is exactly the 'difference' I am suggesting we remove. See option #1 above.
 It's simpler

I disagree. After years of experience using & and | is easy (perhaps 'simple'), but, to a begginer it's not at all.

Given that using bit[] will require lots of special cases to explain (see above)

No, I am trying to remove them, see above.
 (and well-defined) to use & and |.

In C and other languages, yes. In D, c'mon we have bit[], surely it can make bit twiddling really nice and easy. It seems bizarre to say the least that we're not using bit[] for bit twiddling but instead using old techniques which are both harder to understand and use (until you're proficient with them).

I think a more detailed proposal would help show the trade-off and true impact of trying to extend bit[] to be used as a replacement for &|.

Ok. I must admit I haven't tried to formalise this idea as yet.
 I don't
 think it's a trivial as you assume. I view bit[] as only being a packed
 array of true/false values (ala Pascal and C++). The exact packing  
 behavior
 is compiler-dependent.

I didn't first consider this but I don't see this as a problem, unless I am mistaken above.
 Other languages have bit arrays - I'm thinking specifically of Pascal's
 packed arrays and STL's bit vectors but there could be others, too. I'm  
 not aware of any that try to use bit arrays to do bit twiddling. They  
 are meant to be memory efficient arrays of true/false values and that's  
 it.

So they're not 'bit' arrays but 'bool' arrays ;) The argument "it hasn't been done before, it's a bad idea" is weak. Regan
Aug 21 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
 I'm saying, slicing without copying or assigning is not allowed, thus the
 bit[] type does not need to handle the packing of the bits. Instead on 
 assignment the compiler handles it by assigning to them as it finds them. 
 When copying it makes new data, copying from the old data and no changes 
 are required to bit[] to handle this case.

So I guess the proposal is: Statements of the form "<bit array slice> = var[a .. b];" or "var[a .. b] = <bit array slice>;" or "var[a .. b] = <bit-value>;" are allowed when var is an lvalue of numeric type. Restrictions on a and b to byte-boundaries may apply. No other use of slicing a numeric type is allowed. The type of "var[a .. b]" is not defined. Only allowing slicing in copying or assignment contexts is too restricted IMHO. I agree if that's the proposal then the compiler can figure out the endianness and other issues. Given that such constructs can easily be implemented using functions I don't think it's worth the weight of adding special cases to the language.
 Other languages have bit arrays - I'm thinking specifically of Pascal's
 packed arrays and STL's bit vectors but there could be others, too. I'm 
 not aware of any that try to use bit arrays to do bit twiddling. They 
 are meant to be memory efficient arrays of true/false values and that's 
 it.

So they're not 'bit' arrays but 'bool' arrays ;) The argument "it hasn't been done before, it's a bad idea" is weak.

I mentioned other languages because 1) bit arrays are old concepts 2) other languages don't use them for bit twiddling 3) D is alot like those other languages and I'm sure people have tried using bit arrays for bit twiddling in those other languages, too. It's not an unusual request to have bit[] help with twiddling.
Aug 21 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Sun, 21 Aug 2005 20:20:19 -0400, Ben Hinkle <ben.hinkle gmail.com>  
wrote:
 I'm saying, slicing without copying or assigning is not allowed, thus  
 the
 bit[] type does not need to handle the packing of the bits. Instead on
 assignment the compiler handles it by assigning to them as it finds  
 them.
 When copying it makes new data, copying from the old data and no changes
 are required to bit[] to handle this case.

So I guess the proposal is: Statements of the form "<bit array slice> = var[a .. b];" or "var[a .. b] = <bit array slice>;" or "var[a .. b] = <bit-value>;" are allowed when var is an lvalue of numeric type.

Yes.
 Restrictions on a and b to byte-boundaries may
 apply.

Assuming "<bit array slice>" above means "b[x..y]" (or "b[]") and not simply "b" (reference to bit array) then, no. There need not be any restriction to byte-boundaries.
 No other use of slicing a numeric type is allowed. The type of "var[a ..  
 b]" is not defined.

Correct. Except that this type is implicitly castable to a <bit array slice>, eg. b[] = var[a..b]; b[a..b] = var[a..b];
 Only allowing slicing in copying or assignment contexts is too restricted
 IMHO. I agree if that's the proposal then the compiler can figure out the
 endianness and other issues. Given that such constructs can easily be
 implemented using functions I don't think it's worth the weight of adding
 special cases to the language.

You're entitled to your own opinion, mine is: It wouldn't be a "special case", it would be the "standard"/"best way" to manipulate bits in the general case. It would be _much_ nicer than using functions as it would be allow shorter more concise yet more descriptive code. For example, a challenge: What would the following code look like using your proposed functions? //take certain bits from 3 different variables, build a new variable uint newVar; ubyte varOne; ushort varTwo; uint varThree; newVar[0..8] = varOne[3..11]; newVar[8..16] = varTwo[5..13]; newVar[16..32] = varThree[7..23]; I expect the code above to: - look nicer - be clearer - be more concise than anything you can come up with. However I am wary about you being able to come up with something ;)
 Other languages have bit arrays - I'm thinking specifically of Pascal's
 packed arrays and STL's bit vectors but there could be others, too. I'm
 not aware of any that try to use bit arrays to do bit twiddling. They
 are meant to be memory efficient arrays of true/false values and that's
 it.

So they're not 'bit' arrays but 'bool' arrays ;) The argument "it hasn't been done before, it's a bad idea" is weak.

I mentioned other languages because 1) bit arrays are old concepts 2) other languages don't use them for bit twiddling 3) D is alot like those other languages and I'm sure people have tried using bit arrays for bit twiddling in those other languages, too. It's not an unusual request to have bit[] help with twiddling.

Sure, but it's still a weak argument IMO. Regan
Aug 21 2005
next sibling parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
 Only allowing slicing in copying or assignment contexts is too restricted
 IMHO. I agree if that's the proposal then the compiler can figure out the
 endianness and other issues. Given that such constructs can easily be
 implemented using functions I don't think it's worth the weight of adding
 special cases to the language.

You're entitled to your own opinion, mine is: It wouldn't be a "special case", it would be the "standard"/"best way" to manipulate bits in the general case.

I say special case because it would be the only construct in D that takes an expression (the indexing and assignment expression) and forces them to appear in their special statement form. Other expressions in D have types and can be assigned to variables and passed to functions or used as subexpressions. Compared to other expressions and statements in D it is very special.
 It would be _much_ nicer than using  functions as it would be allow 
 shorter more concise yet more descriptive  code.

 For example, a challenge:

 What would the following code look like using your proposed functions?

 //take certain bits from 3 different variables, build a new variable
 uint newVar;
 ubyte varOne;
 ushort varTwo;
 uint  varThree;

 newVar[0..8] = varOne[3..11];
 newVar[8..16] = varTwo[5..13];
 newVar[16..32] = varThree[7..23];

The proposal written above didn't mention copying one var[a..b] to another var[a..b] so that's another case to add.
 I expect the code above to:
  - look nicer
  - be clearer
  - be more concise

sigh. There's more to adding features than making a small set of user code "more concise".
 than anything you can come up with. However I am wary about you being able 
 to come up with something ;)

The most obvious API that comes to mind using a single function is copybits(newVar,0,8,varOne,3,11); The newVar is 'inout'. The varOne is 'in'. Seems like a trivial rewrite of your syntax to me. The benefits of these functions are: 1) no special case 2) users can immediately use them without having to learn a special syntax 3) no confusion with mistaking newVar and varOne with an array
Aug 21 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Sun, 21 Aug 2005 21:45:44 -0400, Ben Hinkle <ben.hinkle gmail.com>  
wrote:
 I say special case because it would be the only construct in D that  
 takes an
 expression (the indexing and assignment expression) and forces them to
 appear in their special statement form. Other expressions in D have types
 and can be assigned to variables and passed to functions or used as
 subexpressions. Compared to other expressions and statements in D it is  
 very special.

I need a concrete example to understand the problem here.
 It would be _much_ nicer than using  functions as it would be allow
 shorter more concise yet more descriptive  code.

 For example, a challenge:

 What would the following code look like using your proposed functions?

 //take certain bits from 3 different variables, build a new variable
 uint newVar;
 ubyte varOne;
 ushort varTwo;
 uint  varThree;

 newVar[0..8] = varOne[3..11];
 newVar[8..16] = varTwo[5..13];
 newVar[16..32] = varThree[7..23];

The proposal written above didn't mention copying one var[a..b] to another var[a..b] so that's another case to add.

It's just using 2 of the cases that were mentioned at the same time. How is it "another case to add"?
 I expect the code above to:
  - look nicer
  - be clearer
  - be more concise

sigh. There's more to adding features than making a small set of user code "more concise".

The goal of this suggestion is to make working with bits easier. Part of that is being able to do things without strange and/or complicated code. Part of that is then having a nice concise syntax. Part of that is having a syntax that is clear as to what it's doing. As you've already mentioned there are many pitfalls when dealing with bits eg. little/big endian byte ordering, packing, etc. Having the compiler (or functions) handle them is a huge bonus. Having the compiler handle it with a built-in syntax is a bit (no pun intended) nicer than using functions. I have yet to understand the problem with the "special case" you keep mentioning. The only special case I see so far is the fact that copying/assigning is required if slicing over byte boundaries.
 than anything you can come up with. However I am wary about you being  
 able to come up with something ;)

The most obvious API that comes to mind using a single function is copybits(newVar,0,8,varOne,3,11); The newVar is 'inout'. The varOne is 'in'. Seems like a trivial rewrite of your syntax to me. The benefits of these functions are: 1) no special case 2) users can immediately use them without having to learn a special syntax

Users either have to learn: - the existance of the module AND the function names AND what they do. - the fact that you can slice a basic type to obtain bits AND the restriction that you must copy or assign over byte boundaries The latter requires one or two sentences of explanation (assuming they know what slicing is, which they will or will need to in order to use D anyway).
 3) no confusion with mistaking newVar and varOne with an array

I can't see how this is a problem at all. A variable _is_ (effectively) an array when you can slice it for bits. It's no different(*) to any other array (or class pretending to be an array). *the differences play no part when you're reading existing code rather than writing new code. Out of context you'll assume (correctly) that it's an array, no problem. In context you'll (correctly) see it as an array of bit[], again, no problem. Regan
Aug 21 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Mon, 22 Aug 2005 14:54:43 +1200, Regan Heath <regan netwin.co.nz> wrote:
 On Sun, 21 Aug 2005 21:45:44 -0400, Ben Hinkle <ben.hinkle gmail.com>  
 wrote:
 I say special case because it would be the only construct in D that  
 takes an
 expression (the indexing and assignment expression) and forces them to
 appear in their special statement form. Other expressions in D have  
 types
 and can be assigned to variables and passed to functions or used as
 subexpressions. Compared to other expressions and statements in D it is  
 very special.

I need a concrete example to understand the problem here.

Are you saying that: uint i; cannot be assigned to a variable, eg. bit[] j = i[0..3]; cannot be a sub-expresion, eg. bit[] j = i[0..3] = 1; or passed to a function, eg. foo(i[0..3]); If so, you're quite correct about the assigned to a variable part. Due to byte boundary issues this: bit[] j = i[0..3]; is illegal, however: bit[3] j; j[] = i[0..3]; and: bit[] j; j.length = 3; j[] = i[0..3]; are both legal. That said, if the slice started on a byte boundary it would be _possible_ to allow it. I doubt many people would like/accept the inconsistency there however. As for the others, an expression like: bit[] j = i[0..3] = 1; is processed like any other expression, in 2 sub-expressions. The first sub-expression "i[0..3] = 1" sets the bits in the variable 'i' to 1. (as previously described) The seccond "j = i[0..3]" is illegal (as previously described). It could instead be written as: bit[3] j; j[] = i[0..3] = 1; The same applies to the function call it creates a bit[] or bit[3] on the stack copying the bits from the source and passing it to the function. Regan
Aug 21 2005
next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Mon, 22 Aug 2005 17:23:11 +1200, Regan Heath wrote:

 On Mon, 22 Aug 2005 14:54:43 +1200, Regan Heath <regan netwin.co.nz> wrote:
 On Sun, 21 Aug 2005 21:45:44 -0400, Ben Hinkle <ben.hinkle gmail.com>  
 wrote:
 I say special case because it would be the only construct in D that  
 takes an
 expression (the indexing and assignment expression) and forces them to
 appear in their special statement form. Other expressions in D have  
 types
 and can be assigned to variables and passed to functions or used as
 subexpressions. Compared to other expressions and statements in D it is  
 very special.

I need a concrete example to understand the problem here.

Are you saying that: uint i; cannot be assigned to a variable, eg. bit[] j = i[0..3]; cannot be a sub-expresion, eg. bit[] j = i[0..3] = 1; or passed to a function, eg. foo(i[0..3]); If so, you're quite correct about the assigned to a variable part. Due to byte boundary issues this: bit[] j = i[0..3]; is illegal, however: bit[3] j; j[] = i[0..3]; and: bit[] j; j.length = 3; j[] = i[0..3]; are both legal. That said, if the slice started on a byte boundary it would be _possible_ to allow it. I doubt many people would like/accept the inconsistency there however. As for the others, an expression like: bit[] j = i[0..3] = 1; is processed like any other expression, in 2 sub-expressions. The first sub-expression "i[0..3] = 1" sets the bits in the variable 'i' to 1. (as previously described) The seccond "j = i[0..3]" is illegal (as previously described). It could instead be written as: bit[3] j; j[] = i[0..3] = 1; The same applies to the function call it creates a bit[] or bit[3] on the stack copying the bits from the source and passing it to the function.

The more I see examples of your proposal, the more I like another way of doing it. Its just *too* misleading in my mind. I keep seeing arrays of integers and not arrays of bits ;-) -- Derek (skype: derek.j.parnell) Melbourne, Australia 22/08/2005 4:30:20 PM
Aug 21 2005
parent "Regan Heath" <regan netwin.co.nz> writes:
On Mon, 22 Aug 2005 16:35:48 +1000, Derek Parnell <derek psych.ward> wrote:
 On Mon, 22 Aug 2005 17:23:11 +1200, Regan Heath wrote:

 On Mon, 22 Aug 2005 14:54:43 +1200, Regan Heath <regan netwin.co.nz>  
 wrote:
 On Sun, 21 Aug 2005 21:45:44 -0400, Ben Hinkle <ben.hinkle gmail.com>
 wrote:
 I say special case because it would be the only construct in D that
 takes an
 expression (the indexing and assignment expression) and forces them to
 appear in their special statement form. Other expressions in D have
 types
 and can be assigned to variables and passed to functions or used as
 subexpressions. Compared to other expressions and statements in D it  
 is
 very special.

I need a concrete example to understand the problem here.

Are you saying that: uint i; cannot be assigned to a variable, eg. bit[] j = i[0..3]; cannot be a sub-expresion, eg. bit[] j = i[0..3] = 1; or passed to a function, eg. foo(i[0..3]); If so, you're quite correct about the assigned to a variable part. Due to byte boundary issues this: bit[] j = i[0..3]; is illegal, however: bit[3] j; j[] = i[0..3]; and: bit[] j; j.length = 3; j[] = i[0..3]; are both legal. That said, if the slice started on a byte boundary it would be _possible_ to allow it. I doubt many people would like/accept the inconsistency there however. As for the others, an expression like: bit[] j = i[0..3] = 1; is processed like any other expression, in 2 sub-expressions. The first sub-expression "i[0..3] = 1" sets the bits in the variable 'i' to 1. (as previously described) The seccond "j = i[0..3]" is illegal (as previously described). It could instead be written as: bit[3] j; j[] = i[0..3] = 1; The same applies to the function call it creates a bit[] or bit[3] on the stack copying the bits from the source and passing it to the function.

The more I see examples of your proposal, the more I like another way of doing it. Its just *too* misleading in my mind. I keep seeing arrays of integers and not arrays of bits ;-)

The question is then, where does the problem lie, in the proposal or in your mind ;) I don't have the same problem with it, but then perhaps _I_ am strange. You're seeing arrays (correctly, because they are in this case) but you're assuming integers, so, if bit literals had some sort of suffix (I guess the binary suffix is it?) then you could, if you so chose, make it more obvious i.e. i[0..3] = 1b i[3..8] = 0b So, you could code like that, I could code without, both of us are happy (until you have to read my code perhaps) Regan
Aug 22 2005
prev sibling parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"Regan Heath" <regan netwin.co.nz> wrote in message
news:opsvv88xxi23k2f5 nrage.netwin.co.nz...
 On Mon, 22 Aug 2005 14:54:43 +1200, Regan Heath <regan netwin.co.nz>
 wrote:
 On Sun, 21 Aug 2005 21:45:44 -0400, Ben Hinkle <ben.hinkle gmail.com>
 wrote:
 I say special case because it would be the only construct in D that
 takes an
 expression (the indexing and assignment expression) and forces them to
 appear in their special statement form. Other expressions in D have
 types
 and can be assigned to variables and passed to functions or used as
 subexpressions. Compared to other expressions and statements in D it is
 very special.

I need a concrete example to understand the problem here.

Are you saying that: uint i; cannot be assigned to a variable, eg. bit[] j = i[0..3]; cannot be a sub-expresion, eg. bit[] j = i[0..3] = 1; or passed to a function, eg. foo(i[0..3]); If so, you're quite correct about the assigned to a variable part. Due to byte boundary issues this: bit[] j = i[0..3]; is illegal, however: bit[3] j; j[] = i[0..3]; and: bit[] j; j.length = 3; j[] = i[0..3]; are both legal. That said, if the slice started on a byte boundary it would be _possible_ to allow it. I doubt many people would like/accept the inconsistency there however.

There is a big difference between j[] = i[a..b] and j = i[a..b] no matter what the byte boundaries are. Consider big-endian machines with trying to slice shorts and longs where the bit[] packing unit is a byte. Short is positioned in memory as 1 0 where the number "1" means that byte stores the data starting at bit 8*1. Long as 7 6 5 4 3 2 1 0 Assuming bit[] is made of a pointer and length with the pointer at the low memory value it is reverse of the endian order (bit[] is currently independent of endianness). Implementing bit[] with the pointer at the high byte and decreasing might work for setting bits but it wouldn't mesh with D's existing array semantics of increasing indices mapping to increasing memory locations. Plus resizing a bit[] with decreasing contents would be very different than resizing a standard array. That's why I think the most practical suggestion was your original restriction of only allowing the slicing if it is immediately copied and never exists as a bit[]. But then I think that's too large a restriction to be useful.
Aug 22 2005
parent "Regan Heath" <regan netwin.co.nz> writes:
On Mon, 22 Aug 2005 18:39:34 -0400, Ben Hinkle <bhinkle mathworks.com>  
wrote:
 That said, if the slice started on a byte boundary it would be  
 _possible_ to allow it. I doubt many people would like/accept the  
 inconsistency there however.

There is a big difference between j[] = i[a..b] and j = i[a..b] no matter what the byte boundaries are. Consider big-endian machines with trying to slice shorts and longs where the bit[] packing unit is a byte. Short is positioned in memory as 1 0 where the number "1" means that byte stores the data starting at bit 8*1. Long as 7 6 5 4 3 2 1 0 Assuming bit[] is made of a pointer and length with the pointer at the low memory value it is reverse of the endian order (bit[] is currently independent of endianness). Implementing bit[] with the pointer at the high byte and decreasing might work for setting bits but it wouldn't mesh with D's existing array semantics of increasing indices mapping to increasing memory locations. Plus resizing a bit[] with decreasing contents would be very different than resizing a standard array. That's why I think the most practical suggestion was your original restriction of only allowing the slicing if it is immediately copied and never exists as a bit[].

You're right. I agree.
 But then I think that's too large a restriction to be useful.

It doesn't stop you twiddling bits and it doesn't stop you forming a new variable from a collection of bits via bit copying. So, it achieves the desired goals. It does stop you from referencing part of an existing variable then later twiddling or reading them, but then that wasn't what it was supposed to achieve, and it can be achieved with a pointer to the original variable and later slicing. Regan
Aug 22 2005
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Mon, 22 Aug 2005 13:14:39 +1200, Regan Heath wrote:

[snip]
 
 What would the following code look like using your proposed functions?
 
 //take certain bits from 3 different variables, build a new variable
 uint newVar;
 ubyte varOne;
 ushort varTwo;
 uint  varThree;
 
 newVar[0..8] = varOne[3..11];
 newVar[8..16] = varTwo[5..13];
 newVar[16..32] = varThree[7..23];
 
 I expect the code above to:
   - look nicer
   - be clearer
   - be more concise
 
 than anything you can come up with. However I am wary about you being able  
 to come up with something ;)

My issue with this idea is that just by looking at 'newVar[0..8]' it gives the impression that newVar is an array. And I don't mean an array of bits ;-) Of course all data ultimately is stored as array(s) of bits so this syntax is a tad misleading. I can see a point to the argument that it would be useful to have the compiler help coders who need to access variables at the bit level. But it would need a different syntax to avoid ambiguities. Seeing that all data is ultimately a set of bits, and is thus intrinsic to the variable, maybe an in-built property of '.bits' might be a useful idea. newVar.bits[0..8] = varOne.bits[3..11]; newVar.bits[8..16] = varTwo.bits[5..13]; newVar.bits[16..32] = varThree.bits[7..23]; And the compiler can do the Endian transformations on the coder's behalf. D would just define that the .bits property is always used as if the data is really stored as Big Endian (ie. Motorola/IBM style and not Intel/VAX style). -- Derek (skype: derek.j.parnell) Melbourne, Australia 22/08/2005 11:51:58 AM
Aug 21 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Mon, 22 Aug 2005 12:26:49 +1000, Derek Parnell <derek psych.ward> wrote:
 On Mon, 22 Aug 2005 13:14:39 +1200, Regan Heath wrote:

 [snip]

 What would the following code look like using your proposed functions?

 //take certain bits from 3 different variables, build a new variable
 uint newVar;
 ubyte varOne;
 ushort varTwo;
 uint  varThree;

 newVar[0..8] = varOne[3..11];
 newVar[8..16] = varTwo[5..13];
 newVar[16..32] = varThree[7..23];

 I expect the code above to:
   - look nicer
   - be clearer
   - be more concise

 than anything you can come up with. However I am wary about you being  
 able
 to come up with something ;)

My issue with this idea is that just by looking at 'newVar[0..8]' it gives the impression that newVar is an array.

And it is.
 And I don't mean an array of bits

But that's exactly what it is.
 ;-) Of course all data ultimately is stored as array(s) of bits so this
 syntax is a tad misleading.

What problems can you see it causing?
 I can see a point to the argument that it would be useful to have the
 compiler help coders who need to access variables at the bit level. But  
 it would need a different syntax to avoid ambiguities.

I don't yet see any problem with "ambiguities". A variable is a collection of bits.
 Seeing that all data is ultimately a set of bits, and is thus intrinsic  
 to the variable, maybe an in-built property of '.bits' might be a useful  
 idea.

  newVar.bits[0..8] = varOne.bits[3..11];
  newVar.bits[8..16] = varTwo.bits[5..13];
  newVar.bits[16..32] = varThree.bits[7..23];

That's 4 more chars I have to type, for no gain. IMO.
 And the compiler can do the Endian transformations on the coder's behalf.

That is a crucial part of the idea it makes bit manipulation much easier. Regan
Aug 21 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Mon, 22 Aug 2005 15:00:45 +1200, Regan Heath wrote:


[snip]
 My issue with this idea is that just by looking at 'newVar[0..8]' it  
 gives the impression that newVar is an array.

And it is.
 And I don't mean an array of bits

But that's exactly what it is.
 ;-) Of course all data ultimately is stored as array(s) of bits so this
 syntax is a tad misleading.


All data is a set of bits, but nearly all data is never used this way. Data is used in conceptual ways rather than implementational ways. And therefore, assuming we give common usage better support than rare usage, we should use special syntax to indicate rare usage.
 What problems can you see it causing?

Confusion. What is the mistake here ... uint newVar; newVar[0..8] = 255; Its hard to tell, no? I actually meant to code ... uint[8] newVar; newVar[0..8] = 255; Now how would the compiler know that? But consider this ... uint newVar; newVar.bits[0..8] = 255; Anyone see the ambiguity here? Neither can I.
 I can see a point to the argument that it would be useful to have the
 compiler help coders who need to access variables at the bit level. But  
 it would need a different syntax to avoid ambiguities.

I don't yet see any problem with "ambiguities". A variable is a collection of bits.

Yes, but its not as commonly thought of as that, is it? Sure, there are cases when one *has* to bit twiddle, but these are rare. As a code reader, if I saw 'RecordCount[0]' I would be thinking the it was referring to the first RecordCount value and not the first bit in the record count value. It is visually confusing, so why bother with it.
 Seeing that all data is ultimately a set of bits, and is thus intrinsic  
 to the variable, maybe an in-built property of '.bits' might be a useful  
 idea.

  newVar.bits[0..8] = varOne.bits[3..11];
  newVar.bits[8..16] = varTwo.bits[5..13];
  newVar.bits[16..32] = varThree.bits[7..23];

That's 4 more chars I have to type, for no gain. IMO.

Legibility is a huge gain! Making code unambiguous and/or easier to read is saving maintenance costs. Code is read much more frequently than written, so the 'pain' of typing four characters is paid for many times over because people read it better.
 And the compiler can do the Endian transformations on the coder's behalf.

That is a crucial part of the idea it makes bit manipulation much easier.

Yes! -- Derek (skype: derek.j.parnell) Melbourne, Australia 22/08/2005 1:03:59 PM
Aug 21 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Mon, 22 Aug 2005 13:19:13 +1000, Derek Parnell <derek psych.ward> wrote:
 My issue with this idea is that just by looking at 'newVar[0..8]' it
 gives the impression that newVar is an array.

And it is.
 And I don't mean an array of bits

But that's exactly what it is.
 ;-) Of course all data ultimately is stored as array(s) of bits so this
 syntax is a tad misleading.


All data is a set of bits, but nearly all data is never used this way. Data is used in conceptual ways rather than implementational ways.

I agree totally. When it 'conceptually' makes sense you will use [] and slice an int, otherwise you wont.
 And therefore, assuming we give common usage better support than rare  
 usage,

We already do. 'a' is easier to use and type than 'a[x..y]'
 we should use special syntax to indicate rare usage.

Sure, that's what I am suggesting. [] _is_ special syntax. It indicates slicing, which is exactly what we're doing.
 What problems can you see it causing?

Confusion. What is the mistake here ... uint newVar; newVar[0..8] = 255;

What is the context?
 Its hard to tell, no?

Without context, yes.
 I actually meant to code ...

  uint[8] newVar;
  newVar[0..8] = 255;

 Now how would the compiler know that?

It wont, nor is it supposed to. The compiler verifies the code is legal, in some situations it can provide additional help. This example, like _many_ others, is not one of them.
 But consider this ...

  uint newVar;
  newVar.bits[0..8] = 255;

 Anyone see the ambiguity here? Neither can I.

A clunky syntax is unlikely to collide with any existing stuff by it's very nature ;) I understand your point, I just disagree that there is any(*) more likelihood of problems here than other features where a typo can and does mean something other than the programmer intended. *where 'any' is defined as some really small number/value.
 I can see a point to the argument that it would be useful to have the
 compiler help coders who need to access variables at the bit level. But
 it would need a different syntax to avoid ambiguities.

I don't yet see any problem with "ambiguities". A variable is a collection of bits.

Yes, but its not as commonly thought of as that, is it? Sure, there are cases when one *has* to bit twiddle, but these are rare.

Sure, bit twiddling is rare.
 As a code reader,  if I saw 'RecordCount[0]' I would be thinking the it  
 was referring to the first RecordCount value

And you'd be correct. The 'value' is a bit and RecordCount is a collection of bits.
 and not the first bit in the
 record count value. It is visually confusing, so why bother with it.

It's not visually confusing because it's idential to slicing any other sort of array, and further it will only occur in situations where it makes sense conceptually. In other words you're only going to be using it when you want to reference the bits of something. Thus the variable will be named appropriately i.e. 'fields' or 'rawData' or something and "if (fields[IS_BINARY])" would make perfect sense. You cannot ignore context.
 Seeing that all data is ultimately a set of bits, and is thus intrinsic
 to the variable, maybe an in-built property of '.bits' might be a  
 useful
 idea.

  newVar.bits[0..8] = varOne.bits[3..11];
  newVar.bits[8..16] = varTwo.bits[5..13];
  newVar.bits[16..32] = varThree.bits[7..23];

That's 4 more chars I have to type, for no gain. IMO.

Legibility is a huge gain! Making code unambiguous and/or easier to read is saving maintenance costs. Code is read much more frequently than written, so the 'pain' of typing four characters is paid for many times over because people read it better.

Sure, but, I still see 'no gain' in the above because I don't agree that it 'solves' any problem that the original syntax had. I believe the original syntax is as legible and unambiguous as any other instance of slicing. Regan
Aug 21 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Mon, 22 Aug 2005 15:51:38 +1200, Regan Heath wrote:

 
 Sure, but, I still see 'no gain' in the above because I don't agree that  
 it 'solves' any problem that the original syntax had. I believe the  
 original syntax is as legible and unambiguous as any other instance of  
 slicing.

The joke is that Walter's not going to do either anyway. ;-) -- Derek (skype: derek.j.parnell) Melbourne, Australia 22/08/2005 2:23:18 PM
Aug 21 2005
parent "Regan Heath" <regan netwin.co.nz> writes:
On Mon, 22 Aug 2005 14:24:38 +1000, Derek Parnell <derek psych.ward> wrote:
 On Mon, 22 Aug 2005 15:51:38 +1200, Regan Heath wrote:


 Sure, but, I still see 'no gain' in the above because I don't agree that
 it 'solves' any problem that the original syntax had. I believe the
 original syntax is as legible and unambiguous as any other instance of
 slicing.

The joke is that Walter's not going to do either anyway. ;-)

We can but hope. Regan
Aug 21 2005