Velocity Reviews > Precedence Misunderstanding

# Precedence Misunderstanding

Ben Pfaff
Guest
Posts: n/a

 07-17-2012
Rui Maciel <(E-Mail Removed)> writes:

> Ben Pfaff wrote:
>
>> I think there's a lot of confusion on this point because we
>> side effects don't exist in math, so order of evaluation doesn't
>> matter. Precedence does, but that's a different issue.

> <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.

Philip Lantz
Guest
Posts: n/a

 07-18-2012
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.

Ike Naar
Guest
Posts: n/a

 07-18-2012
On 2012-07-18, Philip Lantz <(E-Mail Removed)> wrote:
> 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.

Nick Keighley
Guest
Posts: n/a

 07-18-2012
On Jul 17, 7:35*pm, "Charles Richmond" <(E-Mail Removed)>
wrote:
> "Ben Pfaff" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
> > Charles Richmond <(E-Mail Removed)> writes:

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

<snip>

> > Consider 2 * 3 + 4 * 5. *Precedence says that this must be
> > treated the same as (2 * 3) + (4 * 5). *But once you figure that
> > out, you have a choice: you can evaluate 2 * 3 first or you can
> > evaluate 4 * 5 first, because the order doesn't matter. *No one
> > bothers to say that you have to evaluate left-to-right or even
> > that you have to evaluate right-to-left, because that would not
> > change the eventual result in any way.

>
> > When side effects come in, the situation changes. *a() + b()
> > might do something completely different depending on which of a()
> > or b() you call first. *Extending it to a() + b() * c(), then
> > precedence comes in. *C doesn't say in what order a(), b(), and
> > c() are evaluated, but it does say that once they are evaluated,
> > you have to multiply b() by c(), not by a().

>
> 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...

> I can *not* understand how "&&" can have a higher precedence than "||"...
> when it seems to make *no* difference in *any* expression I've seen.

BartC
Guest
Posts: n/a

 07-18-2012

"Ike Naar" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed). ..
> On 2012-07-18, Philip Lantz <(E-Mail Removed)> wrote:
>> 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.

a && 0

or:

a || 1

a needn't be evaluated; but it is.

--
Bartc

Rui Maciel
Guest
Posts: n/a

 07-18-2012
Ben Pfaff wrote:

> 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

Ben Pfaff
Guest
Posts: n/a

 07-18-2012
"BartC" <(E-Mail Removed)> writes:

> "Ike Naar" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed). ..
>> On 2012-07-18, Philip Lantz <(E-Mail Removed)> wrote:
>>> 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.

>
>
> 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.

Ben Pfaff
Guest
Posts: n/a

 07-18-2012
Rui Maciel <(E-Mail Removed)> writes:

> Ben Pfaff wrote:
>
>> 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.

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.

Rui Maciel
Guest
Posts: n/a

 07-18-2012
BartC wrote:

>
> 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

Ben Bacarisse
Guest
Posts: n/a

 07-18-2012
Rui Maciel <(E-Mail Removed)> writes:

> BartC wrote:
>
>>
>> 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.

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.)

--
Ben.