Lazy evaluation question

B

Boltar

Why does C do lazy evaluation for logical boolean operations but not
bitwise ones?

Ie: the following program prints "1 2" , not "1 1" under gcc

main()
{
int a = 1;
int b = 1;
0 && ++a;
0 & ++b;
printf("%d %d\n",a,b);
}

Surely the bitwise boolean ops are just as appropriate for doing lazy
evaluation with?

B2003
 
B

Boltar

Surely the bitwise boolean ops are just as appropriate for doing lazy
evaluation with?


That should have read SOME bitwise ops - ie AND and XOR when the left
hand side is zero.

B2003
 
V

vippstar

Why does C do lazy evaluation for logical boolean operations but not
bitwise ones?

Ie: the following program prints "1 2" , not "1 1" under gcc

main()
{
int a = 1;
int b = 1;
0 && ++a;
0 & ++b;
printf("%d %d\n",a,b);

}

Surely the bitwise boolean ops are just as appropriate for doing lazy
evaluation with?
No.
Furthermore, there is no concept of 'lazy evaluation' in C. Perhaps in
Haskell or some other programming language but certainly not in C, not
only that, but I fail to see what lazy evaluation has to do with this.

(a && b) in this expression, b is evaluated ONLY if after 'a' gets
evaluated it is not equal to 0 (or NULL)
(a & b) in this expression both operands are evaluated, then & is
applied to them.

Another example would be with the operator 'sizeof'

Example snip:
--
#include <stdio.h>

int main(void) {
int i = 0;
printf("sizeof(int) = %zu\n", sizeof ++i);
printf("i = %d\n", i); /* will print 'i = 0' */
return 0;
}
 
R

Richard Heathfield

Boltar said:
Why does C do lazy evaluation for logical boolean operations but not
bitwise ones?

Because logical operations are intended to establish the truth or falsity
of an expression, so that appropriate action can be taken in either case.

For example, if the expression is "if it's raining and I'm going out, I'll
need an umbrella", once we've established that it's not raining, we don't
need to know whether or not I'm going out - the falsity of the expression
is already established, so an umbrella is not required.

Another example: "if you're tall enough or can find a stepstool, you can
fetch down that saucepan". Once we've established that you're tall enough,
we don't need to look for a stepstool.

So it makes good sense for C to do lazy evaluation of && and ||.

But bitwise operators are not used to establish truth or falsity. They are
used to calculate the result of a mathematical operation. Lazy evaluation
would be pointless and meaningless.
 
H

Harald van Dijk

That should have read SOME bitwise ops - ie AND and XOR when the left
hand side is zero.

Oh? So you're saying the value of (x ^ y), when x == 0, doesn't depend on
y? What is that value, then, and why?
 
R

Richard Heathfield

(e-mail address removed) said:

Furthermore, there is no concept of 'lazy evaluation' in C. Perhaps in
Haskell or some other programming language but certainly not in C, not
only that, but I fail to see what lazy evaluation has to do with this.

(a && b) in this expression, b is evaluated ONLY if after 'a' gets
evaluated it is not equal to 0 (or NULL)

This is generally what people mean by "lazy evaluation". If you only mean
that the Standard does not define the term, however, then you are correct.
 
T

Tomás Ó hÉilidhe

Boltar said:
Why does C do lazy evaluation for logical boolean operations but not
bitwise ones?

Ie: the following program prints "1 2" , not "1 1" under gcc

main()
{
int a = 1;
int b = 1;
0 && ++a;
0 & ++b;
printf("%d %d\n",a,b);
}

Surely the bitwise boolean ops are just as appropriate for doing lazy
evaluation with?


I'm going to presume you're talking about 0 as a compile-time
constant, rather than an expression which might be zero (and if it is
zero, don't evaluate the right-hand operand).

Before we discuss whether the righthand operand should be evaluated,
it would make more sense to yield a compile error for a bitwise AND with
a constant zero. And nobody would care, right? Because we've no reason to
ever want to bitwise AND with a constant zero.

...and then came along macros. Maybe the left hand operand was
originally a macro, but now, on this platform, it's become a constant
zero. We should be able to do that, right? Sure, we should be able to.

...but then we don't want different behaviour on different systems if
the macro expands to something other than a constant zero.

That's *one* reason why not to perform "short-circuit" evaluation on
bitwise AND.
 
W

Willem

Richard wrote:
) (e-mail address removed) said:
)
)<snip>
)
)> Furthermore, there is no concept of 'lazy evaluation' in C. Perhaps in
)> Haskell or some other programming language but certainly not in C, not
)> only that, but I fail to see what lazy evaluation has to do with this.
)>
)> (a && b) in this expression, b is evaluated ONLY if after 'a' gets
)> evaluated it is not equal to 0 (or NULL)
)
) This is generally what people mean by "lazy evaluation". If you only mean
) that the Standard does not define the term, however, then you are correct.

This is one of the many forms of lazy evaluation, but it's a much more
general term. The term I've heard used for this specific form is
'short-curcuiting'.


Now that we're talking about it anyway, here's a gripe I have about the
logical operators in C:

Why oh why is (a || b) not equivalent to (a ? a : b) [1]
The same way (less useful), (a && b) could be equivalent to (a ? b : 0)

AIUI, now it's (a || b) is (a ? 1 : b ? 1 : 0)
and (a && b) is (a ? b ? 1 : 0 : 0)

1] Of course, a would only be evaluated once, which is the whole point of
the usefulness of this operation.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
B

Boltar

Oh? So you're saying the value of (x ^ y), when x == 0, doesn't depend on
y? What is that value, then, and why?

Yes , my mistake. Should just be AND.

B2003
 
B

Boltar

Now that we're talking about it anyway, here's a gripe I have about the
logical operators in C:

Why oh why is (a || b) not equivalent to (a ? a : b) [1]
The same way (less useful), (a && b) could be equivalent to (a ? b : 0)

And why isn't there a logical XOR operator? eg: a ^^ b

Logical XOR might not be required often but it is required and having
to do
(a && !b) || (!a && b) is hardly efficient or particularly readable.

B2003
 
W

Willem

Boltar wrote:
) Yes , my mistake. Should just be AND.

Why not OR ?


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
B

Boltar

Boltar wrote:

) Yes , my mistake. Should just be AND.

Why not OR ?

Yes , if the LHS value is 0xFFFFFFF or whatever theres no point
evaluating the RHS of a bitwise OR.

B2003
 
B

Boltar

But bitwise operators are not used to establish truth or falsity. They are
used to calculate the result of a mathematical operation. Lazy evaluation
would be pointless and meaningless.

Why? If theres a zero on the LHS of a bitwise AND you know the result
will be zero no matter what is on the RHS so why bother evaluating the
RHS?

B2003
 
W

Willem

Willem wrote:
) Now that we're talking about it anyway, here's a gripe I have about the
) logical operators in C:
)
) Why oh why is (a || b) not equivalent to (a ? a : b) [1]
) The same way (less useful), (a && b) could be equivalent to (a ? b : 0)

Never mind, it hit me a few minutes after I made this post:

It would require the types of a and b to be compatible.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
W

Willem

Boltar wrote:
)> Boltar wrote:
)>
)> ) Yes , my mistake. Should just be AND.
)>
)> Why not OR ?
)
) Yes , if the LHS value is 0xFFFFFFF or whatever theres no point
) evaluating the RHS of a bitwise OR.

The RHS could have side effects.
You don't want those side effects to suddenly not happen on the rare
occasion that the LHS is all-bits-one or all-bits-zero.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
R

Richard Heathfield

Boltar said:
Why? If theres a zero on the LHS of a bitwise AND you know the result
will be zero no matter what is on the RHS so why bother evaluating the
RHS?

That's the kind of thing a good optimising compiler will already do.
 
T

Thad Smith

Boltar said:
Why does C do lazy evaluation for logical boolean operations but not
bitwise ones?

Ie: the following program prints "1 2" , not "1 1" under gcc

main()
{
int a = 1;
int b = 1;
0 && ++a;
0 & ++b;
printf("%d %d\n",a,b);
}

Surely the bitwise boolean ops are just as appropriate for doing lazy
evaluation with?

No, they are not.

An important goal of C was to generate efficient code. The operands of the
logical operators &&, ||, !, and ? must usually be tested at run time for a
true or false value, normally by a conditional branch. There is no extra
cost to short circuit evaluation and it is a short-hand convenience to
programming.

The boolean operators normally map to bit-wise and, or, xor, and
complement, which return a result value. In general, zero is not a special
case for the operators and no zero test is needed. Performing short
circuit evaluation at run time would be added code and execution time with
little payoff.

It would also lead to less useful results using operators with side
effects. Defining
a = b .& c++; /* where .& is defined as bitwise and with no
evaluation of second operand when first operand is 0 */
is less useful than the current
a = b & c++;
for me.

Compilers can and do take advantage of special values when known at compile
time. a += 0; will generate no code on many compilers if a is not
volatile. But if you write
a += 0 * y++;
the compiler must increment y, even though it is not needed for the
determination of a. 0 & ++b in your example code falls into the same category.
 
R

Richard Tobin

Furthermore, there is no concept of 'lazy evaluation' in C. Perhaps in
Haskell or some other programming language but certainly not in C, not
only that, but I fail to see what lazy evaluation has to do with this.

(a && b) in this expression, b is evaluated ONLY if after 'a' gets
evaluated it is not equal to 0 (or NULL)
[/QUOTE]
This is generally what people mean by "lazy evaluation".

No, that's not what's usually meant by lazy evaluation. Lazy
evaluation means delaying evaluation until the result is needed. So
if you call f(a+b), a+b might not be evaluated until (and unless) the
function needs the value of its argument. It's a very general idea.

What's being referred to here is short-circuit evaluation. You could
regard it as a very special case of lazy evaluation, in that the right
operand is not evaluated until the right operand has been determined
to be true.

-- Richard
 
R

Richard Heathfield

Richard Tobin said:
This is generally what people mean by "lazy evaluation".

No, that's not what's usually meant by lazy evaluation.[/QUOTE]

Yes, I accept the correction. I was of course thinking of short-circuiting.
My mistake.
 
B

Ben Bacarisse

Boltar said:
Now that we're talking about it anyway, here's a gripe I have about the
logical operators in C:

Why oh why is (a || b) not equivalent to (a ? a : b) [1]
The same way (less useful), (a && b) could be equivalent to (a ? b : 0)

And why isn't there a logical XOR operator? eg: a ^^ b

Logical XOR might not be required often but it is required and having
to do
(a && !b) || (!a && b) is hardly efficient or particularly readable.

There are lots of simpler options: !a != !b is one.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top