Precedence Misunderstanding

B

Ben Pfaff

Rui Maciel said:
<snip/>

This is nonsense. What you refer as being "side effects" is nothing more
than the result of ignoring an entire subspace of an operator's domain, and
how the components of the subspace you chose to ignore can also influence
how the remaining components are mapped.

Can you expand on that? It sounds like you are referring to
linear algebra or other mathematical concepts, but I do not know
how they apply in this situation.
 
P

Philip Lantz

Ben Bacarisse wrote:
[Referring to an expression containing only && and || operators]
an operand that is further to the right is never evaluated before one
to its left.

Except when one to its left doesn't need to be evaluated.

For example, in
(a || b) && c
with a = 1, a is evaluated, b is not evaluated, and c is evaluated.

The same thing happens in
a && b || c
with a = 0.
 
I

Ike Naar

Ben Bacarisse wrote:
[Referring to an expression containing only && and || operators]
an operand that is further to the right is never evaluated before one
to its left.

Except when one to its left doesn't need to be evaluated.

For example, in
(a || b) && c
with a = 1, a is evaluated, b is not evaluated, and c is evaluated.

It's not a counterexample to what Ben said.
Even in your example, no operand is evaluated before one to its left.
 
N

Nick Keighley

Mr. Pfaff, I *do* understand about "side effects" with expression evaluation
in programming languages.  I understand *why* short circuiting and
guaranteeing the order of execution... *can* be helpful at times.

The crux of what I do *not* understand is this:

Can someone explain how "&&" can have a *higher* precedence than
"||"... when any series of AND's and OR's are just going to be
done left to right???

precedencde determines how the expressions are grouped

A || B && C means A || (B && C) not (A || B) && C

suppose A=T B=F C=?
in the first case the result is determind once A is found to be true
in
the second we have to evaulate C to find the result.

For example, if you have a long series of logical AND's and OR's like this:

    a && b || c || d && x && y || z

How will "&&" having a higher precedence than "||" effect this at all???
ISTM that evaluation would be the *same* if "&&" and "||" were of equal
precedence.

Create any series of AND's and OR's you want, and please show me how the
precedence of "&&'" and "||" will make any difference under the current C
standard.

Also ISTM that in the above expression, it will *not* matter if one adds
parentheses around any operator/operand pair or grouping.  The result seems
to be the same.  Please show me where I'm wrong.

pretty much any expression involving && and || has this property...
 
B

BartC

Ike Naar said:
Ben Bacarisse wrote:
[Referring to an expression containing only && and || operators]
an operand that is further to the right is never evaluated before one
to its left.

Except when one to its left doesn't need to be evaluated.

For example, in
(a || b) && c
with a = 1, a is evaluated, b is not evaluated, and c is evaluated.

It's not a counterexample to what Ben said.
Even in your example, no operand is evaluated before one to its left.

How about:

a && 0

or:

a || 1

a needn't be evaluated; but it is.
 
R

Rui Maciel

Ben said:
Can you expand on that? It sounds like you are referring to
linear algebra or other mathematical concepts, but I do not know
how they apply in this situation.

Consider floating point operations. When a floating-point exception is
raised, the corresponding floating-point status flag is set. This is
described as a "side-effect" of exceptional floating-point operations.

So, although conceptually we may perceive these operators as mapping a set
of floating-point values to a floating-point value, they actually map a set
of floating-point values to a tuple formed by a floating-point value and a
fenv_t state. More specifically, instead of performing a map similar to:

{float x, float y} -> operator(x,y) \in {float}

....these operators actually are similar to:

{float x, float y} -> operator(x,y) \in {float, fenv_t}

So, in this example, just because, conceptually, we tend to ignore the
fenv_t type, it doesn't mean it doesn't exist or that it isn't a part of
these operators' co-domain. It does, and although it tends to be swept
under the proverbial rug, it is very much an integral part of the definition
of these floating-point operators.

The same also happens with elements which are a part of an operator's domain
but are ignored by a programmer. If the outcome of an operator depends on
some state then the state that influences this outcome, along with any flag
that might be set in the process, are naturally a part of these operators'
domain and co-domain. Not being aware of these elements or how they
influence the outcome of a computation doesn't mean that there is a hole in
basic algebra or in lambda calculus.


Rui Maciel
 
B

Ben Pfaff

BartC said:
Ike Naar said:
Ben Bacarisse wrote:
[Referring to an expression containing only && and || operators]
an operand that is further to the right is never evaluated before one
to its left.

Except when one to its left doesn't need to be evaluated.

For example, in
(a || b) && c
with a = 1, a is evaluated, b is not evaluated, and c is evaluated.

It's not a counterexample to what Ben said.
Even in your example, no operand is evaluated before one to its left.

How about:

a && 0

or:

a || 1

a needn't be evaluated; but it is.

"needs to be evaluated" must be interpreted according to C's
rules, of course.
 
B

Ben Pfaff

Rui Maciel said:
Consider floating point operations. When a floating-point exception is
raised, the corresponding floating-point status flag is set. This is
described as a "side-effect" of exceptional floating-point operations.

So, although conceptually we may perceive these operators as mapping a set
of floating-point values to a floating-point value, they actually map a set
of floating-point values to a tuple formed by a floating-point value and a
fenv_t state. More specifically, instead of performing a map similar to:

{float x, float y} -> operator(x,y) \in {float}

...these operators actually are similar to:

{float x, float y} -> operator(x,y) \in {float, fenv_t}

So, in this example, just because, conceptually, we tend to ignore the
fenv_t type, it doesn't mean it doesn't exist or that it isn't a part of
these operators' co-domain. It does, and although it tends to be swept
under the proverbial rug, it is very much an integral part of the definition
of these floating-point operators.

The same also happens with elements which are a part of an operator's domain
but are ignored by a programmer. If the outcome of an operator depends on
some state then the state that influences this outcome, along with any flag
that might be set in the process, are naturally a part of these operators'
domain and co-domain. Not being aware of these elements or how they
influence the outcome of a computation doesn't mean that there is a hole in
basic algebra or in lambda calculus.

I didn't say that there was a hole in basic algebra or lambda
calculus. I said that "we aren't taught about [side effects] in
our math classes" and "That's because side effects don't exist in
math." I stand by those remarks: in the years of math classes
that I took, side effects never came up. If I had spoken up in a
math class, saying "But what about side effects?", no one would
have understood what I was talking about.

Math textbooks don't tell you that you have to evaluate the
terminals from left to right, or in any other order, since the
order of evaluation just doesn't matter without introducing side
effects.
 
R

Rui Maciel

BartC said:
How about:

a && 0

or:

a || 1

a needn't be evaluated; but it is.

According to the C standard, it is and it should. The && operator
guarantees left-to-right evaluation. Therefore, if that expression is
supposed to be C then a needs to be evaluated.


Rui Maciel
 
B

Ben Bacarisse

Rui Maciel said:
According to the C standard, it is and it should. The && operator
guarantees left-to-right evaluation. Therefore, if that expression is
supposed to be C then a needs to be evaluated.

That's true as far as the "abstract machine" is concerned: i.e. the
compiler must act *as if* the 'a' is evaluated, but unless 'a' is
volatile, I'd expect a compiler to optimise it away.

(It's possible that BartC wrote 'a' as a placeholder for a general C
sub-expression in which case the answer depends on the details and your
comment is pretty much the end of the matter.)
 
R

Rui Maciel

Ben said:
I didn't say that there was a hole in basic algebra or lambda
calculus. I said that "we aren't taught about [side effects] in
our math classes" and "That's because side effects don't exist in
math." I stand by those remarks: in the years of math classes
that I took, side effects never came up. If I had spoken up in a
math class, saying "But what about side effects?", no one would
have understood what I was talking about.

As I've said, these "side effects" you mentioned clearly do "exist in math",
and are covered right in basic algebra. If your math classes covered the
basic definition of a function then you obviously did covered them.

I suspect that the only reason you claim otherwise is that you may not be
aware that "side effects" are nothing more than operands and values of any
given operator which you've ignored, and as a consequence you aren't aware
that they are a part of an operator's domain and/or co-domain and how they
influence the result of an operation.

Math textbooks don't tell you that you have to evaluate the
terminals from left to right, or in any other order, since the
order of evaluation just doesn't matter without introducing side
effects.

You are confusing things. The operators in "math textbooks" are not the
same as operators in C. You don't see any operator defined in a "math
textbook" that includes a fenv_t element in its domain or co-domain, nor
does the real numbers set includes overflow or NaN values and flags.
Floating point numbers may have been defined to represent real numbers, and
floating point operators may have been defined to represent a set of
mathematical operators but that doesn't mean they are the same.


Rui Maciel
 
B

Ben Pfaff

Rui Maciel said:
Ben said:
I didn't say that there was a hole in basic algebra or lambda
calculus. I said that "we aren't taught about [side effects] in
our math classes" and "That's because side effects don't exist in
math." I stand by those remarks: in the years of math classes
that I took, side effects never came up. If I had spoken up in a
math class, saying "But what about side effects?", no one would
have understood what I was talking about.

As I've said, these "side effects" you mentioned clearly do "exist in math",
and are covered right in basic algebra. If your math classes covered the
basic definition of a function then you obviously did covered them.

The article I replied to talked about floating-point numbers and
fenv_t. Certainly that's not covered in basic algebra. Are you
referring to some other article?
 
R

Rui Maciel

Ben said:
That's true as far as the "abstract machine" is concerned: i.e. the
compiler must act *as if* the 'a' is evaluated, but unless 'a' is
volatile, I'd expect a compiler to optimise it away.

You shouldn't expect it to, and a compiler better not do it. Not only would
it go against the standard, but there are also some techniques which it
would break. Consider, for example, the following:

<code>
#include <stdio.h>

int do_stuff(void)
{
// do stuff
if(succeeded)
return 0;
else
return 42;
}

int expensive_operation_or_error_handling_function(void)
{
fprintf(stderr,"an error occurred\n");
return 42;
}

int main(void)
{
do_stuff() || expensive_operation_or_error_handling_function();

/* // it is a bit easier on the eyes than:
if(do_stuff())
{
expensive_operation_or_error_handling_function();
}
*/

return 0;
}
</code>


If the compiler optimizes this code so that the operator evaluates the
expensive_operation_or_error_handling_function() prior to calling
do_stuff(), do_stuff() might never be called.


Rui Maciel
 
R

Rui Maciel

Ben said:
The article I replied to talked about floating-point numbers and
fenv_t. Certainly that's not covered in basic algebra. Are you
referring to some other article?

Algebra is a branch of mathematics which covers operators and relations
between sets. These sets aren't limited to the real numbers set, and the
operators aren't limited to the basic mathematical operators that take real
values as operands. In fact, typically the first contact with algebra tends
not to involve real numbers at all, or basic math operators. Take, for
example, how Venn diagrams tend to be presented in kindergarten.

Regarding "side effects", the concepts which I've referred to are indeed
covered, and they tend to be covered right in the very first explanation of
what a function is supposed to be. Once you were taught that a function f
maps elements in a set A to elements in a set B, you covered all the math
that is needed to explain and understand "side effects". No new math is
needed to describe a function assigning a certain value to a flag, or
returning a different value depending on the value stored in any other flag.


Rui Maciel
 
B

Ben Pfaff

Rui Maciel said:
Algebra is a branch of mathematics which covers operators and relations
between sets. These sets aren't limited to the real numbers set, and the
operators aren't limited to the basic mathematical operators that take real
values as operands. In fact, typically the first contact with algebra tends
not to involve real numbers at all, or basic math operators. Take, for
example, how Venn diagrams tend to be presented in kindergarten.

Regarding "side effects", the concepts which I've referred to are indeed
covered, and they tend to be covered right in the very first explanation of
what a function is supposed to be. Once you were taught that a function f
maps elements in a set A to elements in a set B, you covered all the math
that is needed to explain and understand "side effects". No new math is
needed to describe a function assigning a certain value to a flag, or
returning a different value depending on the value stored in any other flag.

Your math classes must have been very different from mine.
 
B

Ben Bacarisse

Rui Maciel said:
You shouldn't expect it to, and a compiler better not do it. Not only would
it go against the standard, but there are also some techniques which it
would break. Consider, for example, the following:

<code>
#include <stdio.h>

int do_stuff(void)
{
// do stuff
if(succeeded)
return 0;
else
return 42;
}

int expensive_operation_or_error_handling_function(void)
{
fprintf(stderr,"an error occurred\n");
return 42;
}

int main(void)
{
do_stuff() || expensive_operation_or_error_handling_function();

/* // it is a bit easier on the eyes than:
if(do_stuff())
{
expensive_operation_or_error_handling_function();
}
*/

return 0;
}
</code>


If the compiler optimizes this code so that the operator evaluates the
expensive_operation_or_error_handling_function() prior to calling
do_stuff(), do_stuff() might never be called.

Eh? I can't see any connection between this code and what I wrote.
 
K

Keith Thompson

Rui Maciel said:
Algebra is a branch of mathematics which covers operators and relations
between sets. These sets aren't limited to the real numbers set, and the
operators aren't limited to the basic mathematical operators that take real
values as operands. In fact, typically the first contact with algebra tends
not to involve real numbers at all, or basic math operators. Take, for
example, how Venn diagrams tend to be presented in kindergarten.

Regarding "side effects", the concepts which I've referred to are indeed
covered, and they tend to be covered right in the very first explanation of
what a function is supposed to be. Once you were taught that a function f
maps elements in a set A to elements in a set B, you covered all the math
that is needed to explain and understand "side effects". No new math is
needed to describe a function assigning a certain value to a flag, or
returning a different value depending on the value stored in any other flag.

In my experience, a mathematical operator or function takes zero
or more operands and yields a value. The operands/arguments are
members of your "set A", and the result is a member of your "set B"
(either of which may or may not be numbers).

If an operator had "side effects" in the C sense, then those side
effects would normally be described as part of the result.

In C, side effects are effects (changes of state) involving something
other than the result of the function or operator. I have not seen
a similar concept applied in mathematics; instead, any such effects
are part of the result (since mathematics is not limited by C's
type system). For example, a mathematical function's result might
be the entire state of a machine, if that's what it's modelling --
and in that case I wouldn't call anything that's part of the machine
state a "side effect".

Do you have a specific concrete example of "side effects" in basic
mathematics?
 
P

Philip Lantz

Ike said:
Ben Bacarisse wrote:
[Referring to an expression containing only && and || operators]
an operand that is further to the right is never evaluated before one
to its left.

Except when one to its left doesn't need to be evaluated.

For example, in
(a || b) && c
with a = 1, a is evaluated, b is not evaluated, and c is evaluated.

It's not a counterexample to what Ben said.
Even in your example, no operand is evaluated before one to its left.

I guess you interpret the word "before" differently than I do.
 
N

Nick Keighley

Ben Pfaff wrote:
I didn't say that there was a hole in basic algebra or lambda
calculus.  I said that "we aren't taught about [side effects] in
our math classes" and "That's because side effects don't exist in
math."  I stand by those remarks: in the years of math classes
that I took, side effects never came up.  If I had spoken up in a
math class, saying "But what about side effects?", no one would
have understood what I was talking about.

As I've said, these "side effects" you mentioned clearly do "exist in math",
and are covered right in basic algebra.  If your math classes covered the
basic definition of a function then you obviously did covered them.

1. maths includes side affects
I suspect that the only reason you claim otherwise is that you may not be
aware that "side effects" are nothing more than operands and values of any
given operator which you've ignored, and as a consequence you aren't aware
that they are a part of an operator's domain and/or co-domain and how they
influence the result of an operation.


You are confusing things.  The operators in "math textbooks" are not the
same as operators in C.  You don't see any operator defined in a "math
textbook" that includes a fenv_t element in its domain or co-domain, nor
does the real numbers set includes overflow or NaN values and flags.

2. maths does not include side effects

Floating point numbers may have been defined to represent real numbers, and
floating point operators may have been defined to represent a set of
mathematical operators but that doesn't mean they are the same.

aren't 1. and 2. contradictory?
 
I

Ike Naar

Ike said:
Ben Bacarisse wrote:
[Referring to an expression containing only && and || operators]
an operand that is further to the right is never evaluated before one
to its left.

Except when one to its left doesn't need to be evaluated.

For example, in
(a || b) && c
with a = 1, a is evaluated, b is not evaluated, and c is evaluated.

It's not a counterexample to what Ben said.
Even in your example, no operand is evaluated before one to its left.

I guess you interpret the word "before" differently than I do.

I interpret it as "earlier in time". In the given example, a and c are
evaluated, and a is evaluated before c is. This is in accordance with
Ben's assertion that "an operand that is further to the right is never
evaluated before one to its left".
For the given example, I would interpret that assertion as:
- the operands in left-to-right order are a, b, c.
- b is not evaluated before a is (since b is not evaluated at all).
- c is not evaluated before a is (since a is evaluated before c is).
- c is not evaluated before b is (since b is not evaluated).

What is your interpretation?
 

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,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top