www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - &&=, ||= ?

reply z gg.com writes:
For integer type, we have (+=, -=, *= /=), e.g.

i += j;

For bool type, why we don't have (&&=, ||=) ?

void f() {
bool b, c;
b &&= c;
}

$ dmd -c aae.d
aae.d:5: expression expected, not '='
aae.d:5: found 'c' when expecting ';' following 'statement'

Is there a reason for this?
Jul 11 2005
next sibling parent reply Mike Parker <aldacron71 yahoo.com> writes:
z gg.com wrote:
 For integer type, we have (+=, -=, *= /=), e.g.
 
 i += j;
 
 For bool type, why we don't have (&&=, ||=) ?
 
 void f() {
 bool b, c;
 b &&= c;
 }
 
 $ dmd -c aae.d
 aae.d:5: expression expected, not '='
 aae.d:5: found 'c' when expecting ';' following 'statement'
 
 Is there a reason for this?
 
 

Jul 11 2005
parent clayasaurus <clayasaurus gmail.com> writes:
Mike Parker wrote:
 z gg.com wrote:
 
 For integer type, we have (+=, -=, *= /=), e.g.

 i += j;

 For bool type, why we don't have (&&=, ||=) ?

 void f() {
 bool b, c;
 b &&= c;
 }

 $ dmd -c aae.d
 aae.d:5: expression expected, not '='
 aae.d:5: found 'c' when expecting ';' following 'statement'

 Is there a reason for this?


I assume it would mean this... (using bool/bit bob) bob = (bob && a); would become bob &&= a;
Jul 11 2005
prev sibling next sibling parent Hasan Aljudy <hasan.aljudy gmail.com> writes:
z gg.com wrote:
 For integer type, we have (+=, -=, *= /=), e.g.
 
 i += j;
 
 For bool type, why we don't have (&&=, ||=) ?
 
 void f() {
 bool b, c;
 b &&= c;
 }
 
 $ dmd -c aae.d
 aae.d:5: expression expected, not '='
 aae.d:5: found 'c' when expecting ';' following 'statement'
 
 Is there a reason for this?
 
 

I think it's just that nobody every needed it or thought about it .. or something like that! we don't work with booleans and manipulate thier values much .. we just use them for control structures i.e. if .. while .. etc. only time I work with booleans is as flags .. the most radical manipulation I would do is toggling them flag = !flag;
Jul 11 2005
prev sibling parent reply "Uwe Salomon" <post uwesalomon.de> writes:
On Tue, 12 Jul 2005 03:25:34 +0200, <z gg.com> wrote:

 For integer type, we have (+=, -=, *= /=), e.g.

 i += j;

 For bool type, why we don't have (&&=, ||=) ?

 void f() {
 bool b, c;
 b &&= c;
 }

 $ dmd -c aae.d
 aae.d:5: expression expected, not '='
 aae.d:5: found 'c' when expecting ';' following 'statement'

 Is there a reason for this?

Yes. For the "bit" type (a && b) and (a & b) are the same, as it is only a single bit. && exists only because integers have more than one bit, but all nonzero values are interpreted as true. Thus, if you want to work with bits, just use &=, |= etc. With integers you have to use the long form, because all op= variants are guaranteed to evaluate the lvalue only once. This is not possible for &&= with, say, an uint. Ciao uwe
Jul 11 2005
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Uwe Salomon wrote:
 On Tue, 12 Jul 2005 03:25:34 +0200, <z gg.com> wrote:

 For bool type, why we don't have (&&=, ||=) ?


 Yes. For the "bit" type (a && b) and (a & b) are the same, as it is 
 only a single bit. && exists only because integers have more than one 
 bit, but all nonzero values are interpreted as true. Thus, if you 
 want to work with bits, just use &=, |= etc.

Unless you want the rvalue to be lazily evaluated. Really b &&= c; should be equivalent to if (b) b = c; and similarly b ||= c; equivalent to if (!b) b = c;
 With integers you have to use the long form, because all op= variants 
 are guaranteed to evaluate the lvalue only once.  This is not 
 possible for &&= with, say, an uint.

What do you mean by this? Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- a->--- UB P+ L E W++ N+++ o K- w++ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Jul 14 2005
parent reply "Uwe Salomon" <post uwesalomon.de> writes:
 With integers you have to use the long form, because all op= variants  
 are guaranteed to evaluate the lvalue only once.  This is not possible  
 for &&= with, say, an uint.

What do you mean by this?

Look at the code equivalent you have given yourself:
 Really

      b &&= c;

 should be equivalent to

      if (b) b = c;

if (b) -- first access to b b = c -- second access to b But the operators += -= |= etc. should evaluate b only once, not twice. By the way, b &&= c should mean something like this: if (b) b = (c != 0); Ciao uwe
Jul 14 2005
next sibling parent "Uwe Salomon" <post uwesalomon.de> writes:
 But the operators +=  -=  |=  etc. should evaluate b only once, not  
 twice.

Though i must add that the generated machine code could be very similar if the compiler does not put the variables in the registers. Both of them load a variable from the stack into a register, change it and write it back to the stack. Ciao uwe
Jul 14 2005
prev sibling next sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Uwe Salomon wrote:
 With integers you have to use the long form, because all op= 
 variants  are guaranteed to evaluate the lvalue only once.  This is 
 not possible  for &&= with, say, an uint.

What do you mean by this?

Look at the code equivalent you have given yourself:

I still don't see how it relates.
 Really

      b &&= c;

 should be equivalent to

      if (b) b = c;

if (b) -- first access to b b = c -- second access to b But the operators += -= |= etc. should evaluate b only once, not twice.

Exactly. I was using b to refer to the evaluation, rather than the expression. Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- a->--- UB P+ L E W++ N+++ o K- w++ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Jul 14 2005
parent reply "Uwe Salomon" <post uwesalomon.de> writes:
 I still don't see how it relates.

 Really

      b &&= c;

 should be equivalent to

      if (b) b = c;

b = c -- second access to b But the operators += -= |= etc. should evaluate b only once, not twice.

Exactly. I was using b to refer to the evaluation, rather than the expression.

Hmm, i don't know how to explain. Perhaps "evaluate" is the wrong word? Look into http://www.digitalmars.com/d/expression.html#AssignExpression If you have this expression: b = b + c; Compiled it will look somehow like this: make a copy of b add c to the copy store the result to b The other variant: b += c; Looks like this when compiled: add c to b See the difference? In the first variant b is "evaluated" twice. This is not as important if you use integers, as the resulting machine code will be the same if they are stored on the stack: mov EAX, b add EAX, c mov b, EAX But if you use user-defined data types, this will be different: b = b.opAdd(c); // versus b.opAddAssign(c); The second one will often be much faster, as the implementation for opAdd will look like this: Type opAdd(Type other) { Type copy = *this; copy.opAddAssign(other); return copy; } Ciao uwe
Jul 14 2005
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Uwe Salomon wrote:
<snip>
 If you have this expression:
 
 b = b + c;
 
 Compiled it will look somehow like this:
 
 make a copy of b
 add c to the copy
 store the result to b
 
 The other variant:
 
 b += c;
 
 Looks like this when compiled:
 
 add c to b
 
 See the difference? In the first variant b is "evaluated" twice.

Unless you add the words "except that b is only evaluated once" to the first explanation. Indeed, this is how it's explained in the spec if you care to read it. Moreover, even if &&= ||= were a special case of being not so easily explainable in words, it would still be equally implementable. Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- a->--- UB P+ L E W++ N+++ o K- w++ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Jul 15 2005
parent Greg Smith <greg siliconoptix.com> writes:
/// I'm discussing C: AFIK applies equally to D

b += c; // LHS evaluated only once.

If 'b' is a simple (non-class) variable, there's no difference between 
"b += c" and "b = b + c".

The difference is important when there is a calculation involved in 
finding the address of the lvalue, and that calculation has (or may
have) side-effects.

    *get_ptr(x)  += 2;

vs.
    *get_ptr(x) = *get_ptr(x) + 2;

the first example makes only 1 call to get_ptr(), the second
will make two. The order in which the two calls are made is
not specified by the C language.

Or,
	a[ i++ ] += 3;
// NOT the same as
	a[ i++ ] = a[i++] + 3;
(the second example is improper C, since the two references to i are
not well-defined relative to the modifications of i)

'calculating' the address of a local variable by adding a constant
to the frame pointer doesn't count, since the result cannot
change during the  execution of a single statement; the
compiler is perfectly free to do that once  for
'b = b+c', or do it twice for 'b+=c'.

[Note: I remember some cheesy old C compilers which generated code
directly out of the parser, such that 'b+=c' would be smaller than
'b = b + c', since the compiler calculated the address of local 'b'
twice in the second case. That is not a language issue, it's a cheesy
compiler issue. The same compiler generated less code for '++i;' than
for 'i++;', enough said ]

Another example:

	arr[i+2] += 4;
	arr[i+2] = arr[i+2] + 4;

Both have the same effect. They may generate different code, depending
on the compiler. But they may not. The distinction between + and +=
doesn't extend to that.

Stewart Gordon wrote:

 Uwe Salomon wrote:
 <snip>
 
 If you have this expression:

 b = b + c;

 Compiled it will look somehow like this:

 make a copy of b
 add c to the copy
 store the result to b

 The other variant:

 b += c;

 Looks like this when compiled:

 add c to b

 See the difference? In the first variant b is "evaluated" twice.

<snip> Unless you add the words "except that b is only evaluated once" to the first explanation. Indeed, this is how it's explained in the spec if you care to read it. Moreover, even if &&= ||= were a special case of being not so easily explainable in words, it would still be equally implementable. Stewart.

Jul 18 2005
prev sibling parent reply Greg Smith <greg siliconoptix.com> writes:
Uwe Salomon wrote:

 With integers you have to use the long form, because all op= 
 variants  are guaranteed to evaluate the lvalue only once.  This is 
 not possible  for &&= with, say, an uint.

What do you mean by this?

Look at the code equivalent you have given yourself:
 Really

      b &&= c;

 should be equivalent to

      if (b) b = c;

if (b) -- first access to b b = c -- second access to b But the operators += -= |= etc. should evaluate b only once, not twice. By the way, b &&= c should mean something like this: if (b) b = (c != 0);

which must be calculated, and its calculation may have side-effects. The calculation will only be done once. {bit * bptr = &b; // the 'evaluated once' means this if (*bptr) *bptr = (c != 0); } I remember a discussion about &&= and ||= about 20 years ago on comp.lang.c, when the ISO standard was being drafted. Yes, they could be done, but they're rather weird; what about int b = 4; int c = ...; // doesn't matter b ||= c; should this leave 'b' as 4, since the evaluation was short-circuited due to b!=0 ?? This is what has been proposed in this thread. Or should it set 'b' to 1, which is what b = b||c does? no thanks. Such an operator would be misunderstood out of proportion to its usefulness, no matter how it is defined. - greg
Jul 18 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Mon, 18 Jul 2005 17:02:24 -0400, Greg Smith wrote:

 Uwe Salomon wrote:
 
 With integers you have to use the long form, because all op= 
 variants  are guaranteed to evaluate the lvalue only once.  This is 
 not possible  for &&= with, say, an uint.

What do you mean by this?

Look at the code equivalent you have given yourself:
 Really

      b &&= c;

 should be equivalent to

      if (b) b = c;

if (b) -- first access to b b = c -- second access to b But the operators += -= |= etc. should evaluate b only once, not twice. By the way, b &&= c should mean something like this: if (b) b = (c != 0);

which must be calculated, and its calculation may have side-effects. The calculation will only be done once. {bit * bptr = &b; // the 'evaluated once' means this if (*bptr) *bptr = (c != 0); } I remember a discussion about &&= and ||= about 20 years ago on comp.lang.c, when the ISO standard was being drafted. Yes, they could be done, but they're rather weird; what about int b = 4; int c = ...; // doesn't matter b ||= c; should this leave 'b' as 4, since the evaluation was short-circuited due to b!=0 ?? This is what has been proposed in this thread. Or should it set 'b' to 1, which is what b = b||c does? no thanks. Such an operator would be misunderstood out of proportion to its usefulness, no matter how it is defined.

LOL... In 'my world' both these would not be allowed because you can't OR non-booleans. This would be okay ... bool b,c; . . . b = b || c; But this would be just silly... int b,c; . . . b = b || c; You could do this though ... b = cast(int) ((b != 0) || (c != 0)); But I digress ... D isn't my perfect language, nor will it ever be. -- Derek Parnell Melbourne, Australia 19/07/2005 7:46:13 AM
Jul 18 2005
parent reply "Uwe Salomon" <post uwesalomon.de> writes:
 LOL... In 'my world' both these would not be allowed because you can't OR
 non-booleans.

   b = cast(int) ((b != 0) || (c != 0));

Hmm. Your world seems to be cluttered with parentheses and casts... Not sure if this is the way to go. :) Ciao uwe
Jul 18 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Tue, 19 Jul 2005 07:41:02 +0200, Uwe Salomon wrote:

 LOL... In 'my world' both these would not be allowed because you can't OR
 non-booleans.

   b = cast(int) ((b != 0) || (c != 0));

Hmm. Your world seems to be cluttered with parentheses and casts... Not sure if this is the way to go. :)

LOL. My point however was that the OP was dealing with numbers, and why does anybody want to logically-or numbers? Booleans I can understand, but numbers? Doesn't make sense to me. It as silly as asking for the square root of "ABC". The point with casts and parenthesizes, is that if you really, really needed to do this, then your code should have obvious flashing warning signs around it. -- Derek Melbourne, Australia 19/07/2005 3:48:07 PM
Jul 18 2005
parent "Uwe Salomon" <post uwesalomon.de> writes:
 My point however was that the OP was dealing with numbers, and why does
 anybody want to logically-or numbers? Booleans I can understand, but
 numbers? Doesn't make sense to me. It as silly as asking for the square
 root of "ABC".

I have often seen things like this when dealing with return values or lengths. API functions from Windows or libc or whatever often return a status code that is of type int. If zero is used to signal an error, and a nonzero value for success, you can write things like this: if (write(f, "xyz") && read(g, &i)) printf("success!"); The same goes for pointers and lengths: if (someObj) delete someObj; Though i must admit that i often write the full expressions because i don't like this kind of abbreviations.
 The point with casts and parenthesizes, is that if you really, really
 needed to do this, then your code should have obvious flashing warning
 signs around it.

Nah, that's too much. Ciao uwe
Jul 18 2005