verifying precedence

R

Roedy Green

consider this line of code:

( Comparator<String> ) (Class.forName( comparatorName
).newInstance());

are the () around Class.forName( comparatorName ).newInstance()
necessary?

You could consult a precedence table, but you could misinterpret it.
Java's rules of precedence and association are quite complicated.

Is there a tool that will tell you:

1. which of your () are nugatory?

2. what your expression means were there no reliance on precedence,
handled purely with ()?

I think this would be a great tool for newbies.
 
J

Joshua Cranmer ðŸ§

"Practical Programming in C" summed up the precedence rules in C
thusly:

" Precedence Operator
1. * / %
2. + -

Put parantheses around everything else."

If the meaning of your code depends on the particulars of operator
precedence beyond the very obvious rules above, rewrite it so that it
doesn't. (The same holds for the difference between ++i and i++.)

That's not quite the right rules, but probably because it's ignoring
half the operators in the first place. I'd remember it as:
1. Unary operators [includes parentheses]
2. * / %
3. + -
4. Relational (<, >, ==, etc.)
5. Logical (&&, ||)
6. ?:
7. = and op=

The position of shift and bitwise operators is the part I can never
remember: C (by accident of history [1]) put the bitwise below
relational operators instead of above it (so you have to say (x & mask)
== mask instead of x & mask == mask). Some descendants fixed the issue,
while others did not, so as someone who regularly uses several different
languages, I can never remember if the language I'm in fixed the
precedence or not.

Note that the table I give glides over the binding of a few operators
(x++ and ++x are different levels, as are < and ==), but in terms of
remembering where I need to put parentheses, it's sufficient.


[1] Logical, short-circuit and and or came much later. That's why the
and pseudo-keyword maps to &, not &&. Arguably, when the logical
operators had been introduced, the bitwise operators ought to have been
moved in precedence, but maybe the authors of C didn't want to risk such
a breaking change at that time.
 
J

Joerg Meier

That's not quite the right rules, but probably because it's ignoring
half the operators in the first place.

I believe that's the point. It's saying not to bother with the rules of the
rest and to just use parenthesis instead, and I'm inclined to agree. Even
if you perfectly know operator precedence, it's still hard to read a
complex statements without parenthesis and intuitively grasp what happens.

Liebe Gruesse,
Joerg
 
J

Joshua Cranmer ðŸ§

^^ Ha, my use of a non-BMP character caught out a newsreader! I'm
guessing it's trying to encode UTF-8 as CESU-8 instead from the number
of characters?
I believe that's the point. It's saying not to bother with the rules of the
rest and to just use parenthesis instead, and I'm inclined to agree. Even
if you perfectly know operator precedence, it's still hard to read a
complex statements without parenthesis and intuitively grasp what happens.

If you took its recommendations strictly, it would advise you to say:
x = ((a + 5) == (b + c));

I was pointing out that it's missing the implicit levels for the
"obvious" operators. In truth, the complexity of the situation is with
the shift and bitwise operators in comparison to everything else and to
themselves. (And, arguably, comparison operators to themselves: a >= b
== c <= d is something I would advocate parenthesizing).
 
S

Stefan Ram

=?UTF-8?B?Sm9zaHVhIENyYW5tZXIg8J+Qpw==?= said:
I was pointing out that it's missing the implicit levels for the
"obvious" operators. In truth, the complexity of the situation is with
the shift and bitwise operators in comparison to everything else and to
themselves. (And, arguably, comparison operators to themselves: a >= b
== c <= d is something I would advocate parenthesizing).

When one is learning a language such as Italien, there are
hundreds and hundreds of individual verb forms one has to
memorize. Let us just have a look at « essere » (=»to be«):

The individual forms of this single verb are: « ente »,
« era », « erano », « eravamo », « eravate », « eri »,
« ero », « essendo », « essere », « fosse », « fossero »,
« fossi », « fossimo », « foste », « fosti », « fu »,
« fui », « fummo », « furono », « sarai », « saranno »,
« saranno », « sarebbe », « sarebbero », « sarei »,
« saremmo », « saremo », « sareste », « saresti »,
« sarete », « sarà », « sarò », « sei », « sia », « siamo »,
« siano », « siano », « siate », « siete », « sii »,
« sono », « sono », « stato », « stati », and « è ».

The learning capabilities of students of Java must be by
orders of magnitude smaller than those of students of
natural languages, when the students of Java can't memorize
the precendence of 37 operators.
 
J

Joshua Cranmer ðŸ§

=?UTF-8?B?Sm9zaHVhIENyYW5tZXIg8J+Qpw==?= <[email protected]> writes:

[ Yet more mangling ! :p ]
The learning capabilities of students of Java must be by
orders of magnitude smaller than those of students of
natural languages, when the students of Java can't memorize
the precendence of 37 operators.

Your analogy isn't quite right here. I don't know Italian, but I do know
some French, so I'll use that here instead in my analogy. French, like
Italian, has a load of different variants [neglecting accents here
because this IME doesn't let me do it easily):
* infinitive (etre),
* 6 present indicative (suis, es, est, sommes, etes, sont)
* 6 simple future (ser + ai, ai, a, ons, ez, ont)
* 6 conditional (ser + ais, ais, ait, ions, iez, aient)
* 6 imperfect (et + ais, ais, ait, ions, iez, aient)
* 6 simple past (fus, fus, fut, fumes, futes, furent)
* 6 present subjunctive (sois, sois, soit, soyons, soyez, soient)
* 6 imperfect subjunctive (fusse, fusses, fut, fussions, fussiez, fussent)
* 3 imperative (sois, soyons, soyez)
* Present participle (etant)
* Past participle (ete)

That's a total of 48 forms (if my math is correct), although if you want
to be a little more precise, 5 of them are repeated. There is a bit of
structure to it (and etre is an unusually complex verb), but I was
unable to list the simple past and imperfect subjunctive without
checking my dictionary. Why? Because I've never had to use them, and
(with the exception of "il fut"), I've never even *seen* them before.

It's like that with operator precedence: sure, there may not be all that
much to learn/memorize, but if you never use it, it's going to leave
your head as quickly as it came in.
 
A

Arne Vajhøj

"Practical Programming in C" summed up the precedence rules in C
thusly:

" Precedence Operator
1. * / %
2. + -

Put parantheses around everything else."

If the meaning of your code depends on the particulars of operator
precedence beyond the very obvious rules above, rewrite it so that it
doesn't. (The same holds for the difference between ++i and i++.)

That's not quite the right rules, but probably because it's ignoring
half the operators in the first place. I'd remember it as:
1. Unary operators [includes parentheses]
2. * / %
3. + -
4. Relational (<, >, ==, etc.)
5. Logical (&&, ||)
6. ?:
7. = and op=

I think it is a pretty good rule.

Use the precedence rules known from very basic math that everybody
knows and use () for the rest.

That reduces the risk of errors. That is good practice.

Arne
 
A

Arne Vajhøj

If you took its recommendations strictly, it would advise you to say:
x = ((a + 5) == (b + c));

Yes.

I think that is how it should be written.

Arne
 
A

Arne Vajhøj

When one is learning a language such as Italien, there are
hundreds and hundreds of individual verb forms one has to
memorize. Let us just have a look at « essere » (=»to be«):

The individual forms of this single verb are: « ente »,
« era », « erano », « eravamo », « eravate », « eri »,
« ero », « essendo », « essere », « fosse », « fossero »,
« fossi », « fossimo », « foste », « fosti », « fu »,
« fui », « fummo », « furono », « sarai », « saranno »,
« saranno », « sarebbe », « sarebbero », « sarei »,
« saremmo », « saremo », « sareste », « saresti »,
« sarete », « sarà », « sarò », « sei », « sia », « siamo »,
« siano », « siano », « siate », « siete », « sii »,
« sono », « sono », « stato », « stati », and « è ».

The learning capabilities of students of Java must be by
orders of magnitude smaller than those of students of
natural languages, when the students of Java can't memorize
the precendence of 37 operators.

Not really.

It takes people 15 years or so to learn to master their primary
language.

I am sure that if Java developers were allowed to study Java for
15 years, then they could be very good in Java syntax and semantics.

(let us ignore the little practical issue of the language changing
over 15 years)

Java developers typical get maybe 2 years to learn the language.

People also learn second and more languages. But many people keep
making small mistakes in their use of a foreign language. Some people
have talent for languages and can become as good as a native speaker,
but that privilege is not given everyone.

But it is not a big problem. If an Italian hear a foreigner use a wrong
form of a verb it will typically not be a problem as the meaning would
still be obvious.

Programming languages are different. A wrong order of execution result
in a bug.

Arne
 
A

Arne Vajhøj

You could consult a precedence table, but you could misinterpret it.
Java's rules of precedence and association are quite complicated.


"Practical Programming in C" summed up the precedence rules in C
thusly:

" Precedence Operator
1. * / %
2. + -

Put parantheses around everything else."

If the meaning of your code depends on the particulars of operator
precedence beyond the very obvious rules above, rewrite it so that it
doesn't. (The same holds for the difference between ++i and i++.)

That's not quite the right rules, but probably because it's ignoring
half the operators in the first place. I'd remember it as:
1. Unary operators [includes parentheses]
2. * / %
3. + -
4. Relational (<, >, ==, etc.)
5. Logical (&&, ||)
6. ?:
7. = and op=

I think it is a pretty good rule.

Use the precedence rules known from very basic math that everybody
knows and use () for the rest.

That reduces the risk of errors. That is good practice.

Or to quote the Java coding convention:

<quote>
Parentheses
It is generally a good idea to use parentheses liberally in expressions
involving mixed operators
to avoid operator precedence problems. Even if the operator precedence
seems clear to you, it
might not be to others—you shouldn’t assume that other programmers know
precedence as
well as you do.
</quote>

Arne
 
R

Roedy Green

Put parantheses around everything else.

That would do for your own code, but will not help you understand
somebody else's code.

In my scid essay, I figure you should configure just how well you
understand the precedence rules and have your IDE remove excess () or
put in extra () to suit without actually changing the code, just the
way it is displayed.

You should also be able to tidy the code to some corporate standard
level of () before checkin.
 
R

Roedy Green

when the students of Java can't memorize
the precendence of 37 operators.

When you are coding Java, even the tiniest misunderstanding of code
can be catastrophic. Natural language is much more forgiving.
 
A

Arne Vajhøj

That would do for your own code, but will not help you understand
somebody else's code.

In my scid essay, I figure you should configure just how well you
understand the precedence rules and have your IDE remove excess () or
put in extra () to suit without actually changing the code, just the
way it is displayed.

That could create some small surprises when two developers are
discussing code or if a developer is trying to find the code associated
with a compile error showing source code.

Arne
 
G

Gene Wirchenko

=?UTF-8?B?Sm9zaHVhIENyYW5tZXIg8J+Qpw==?= <[email protected]> writes:

[ Yet more mangling ! :p ]
The learning capabilities of students of Java must be by
orders of magnitude smaller than those of students of
natural languages, when the students of Java can't memorize
the precendence of 37 operators.

Your analogy isn't quite right here. I don't know Italian, but I do know
some French, so I'll use that here instead in my analogy. French, like
Italian, has a load of different variants [neglecting accents here
because this IME doesn't let me do it easily):
* infinitive (etre),
* 6 present indicative (suis, es, est, sommes, etes, sont)

Just for fun, "je suis" also means "I follow."

Quand je cour, je suis le premier.

When I run I [am|follow] the first.

[snip]

Sincerely,

Gene Wirchenko
 
E

Eric Sosman

[...]
The learning capabilities of students of Java must be by
orders of magnitude smaller than those of students of
natural languages, when the students of Java can't memorize
the precendence of 37 operators.

Precendence iz easie; itts spellign thatts harde.
 
S

Simon Lewis

Chris Uppal said:
One difference here is that, in a natural language, unused forms die out or
acquire new meanings. In a programming language (with current tech, anyway ;-)
that doesn't happen.

So someone using an obscure form doesn't get a "huh?" from the compiler as
would happen with real speech. The compiler is quite happy -- /it/ is an
expert in the language -- but the code may still not be fit for purpose.

Hence the /recommendation/ to use brackets. It could be seen as dumbing down,
it could be seen as "common sense". Another way of seeing it is as
retroactively "fixing" a discovered flaw in the design of the language -- that
it has too many precedence levels (even if they aren't scambled).

-- chris

For anyone wanting any maintainability then bracket it. It takes the
guessing out. I wouldn't dumb down the language use in terms of generics
etc but bracketing is a simple thing to so that removes any doubt.
 

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

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top