473,416 Members | 1,542 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,416 software developers and data experts.

Nested conditional expressions ---- good idea/bad idea?

Below you will see an example of a nested conditional expression that
this colleague of mine loves. He claims that it is more efficient that
a multi-level if-else-if structure. Moreover, our complexity analyzer
tool supposedly does not pick it up. Is it really more efficient?
Personally I find this coding style extremely cryptic, misleading and
error-prone.

I believe that I have removed all traces of proprietary-ness from this
coding example by multiple text substitutions.

--NS
/************************************************** ***********/
#include <stdio.h>

#define QWER 0x1000
#define TYUI 0x2000
#define ASDF 0x4000
#define GHJK 0x8000
#define ZXCV 0x10000
#define BNML 0x20000
void
print_value(int code, int type)
{
printf(" ==> %s, Type %02X \n",
(code == QWER ? "QWER":
code == TYUI ? "TYUI":
code == ASDF ? "ASDF":
code == GHJK ? "GHJK":
code == ZXCV ? "ZXCV":
code == BNML ? "BNML": "????"),
type);
}
main(void)
{
print_value(BNML, 256);
print_value(ZXCV, 512);
print_value(GHJK, 1024);
print_value(ASDF, 768);
print_value(TYUI, 128);
print_value(QWER, 64);
print_value(BNML|QWER, 32);
}

Nov 14 '05 #1
10 3175

ni*************@yahoo.com wrote:
Below you will see an example of a nested conditional expression that
this colleague of mine loves. He claims that it is more efficient that a multi-level if-else-if structure. Moreover, our complexity analyzer tool supposedly does not pick it up. Is it really more efficient?
The idea of efficiency is not a C language issue.
Personally I find this coding style extremely cryptic, misleading and
error-prone.
it is

I believe that I have removed all traces of proprietary-ness from this coding example by multiple text substitutions.

--NS
/************************************************** ***********/
#include <stdio.h>

#define QWER 0x1000
#define TYUI 0x2000
#define ASDF 0x4000
#define GHJK 0x8000
#define ZXCV 0x10000
#define BNML 0x20000
void
print_value(int code, int type)
{
printf(" ==> %s, Type %02X \n",
(code == QWER ? "QWER":
code == TYUI ? "TYUI":
code == ASDF ? "ASDF":
code == GHJK ? "GHJK":
code == ZXCV ? "ZXCV":
code == BNML ? "BNML": "????"),
type);
}
main(void)
{
print_value(BNML, 256);
print_value(ZXCV, 512);
print_value(GHJK, 1024);
print_value(ASDF, 768);
print_value(TYUI, 128);
print_value(QWER, 64);
print_value(BNML|QWER, 32);
}


Efficiency depends on things outside the scope of C (compiler,
processor, etc.). I doubt there would be any meaningful efficiency
gain from doing this, it might even be more inefficient (confuses
compiler's optimization stages?!?). I personally would never write
code like this, and I question the motives of programmers that do
(showing off? making their code harder for other to understand?).

[OT] If this is an embedded system with scarce resources, and you need
every nanosecond of time and bit of memory, then run tests (don't guess
by looking at C code- that is out of the question!!!!). Early on in the
software engineering process, your company probably did a thorough
study of possible "coarse" granular optimization practices that will
help make efficient code for your particular implementation. Stick to
this, but don't play around with little details in the C source (keep
code looking clean). Near the end of your design cycle, if you find you
still need more optimization (which you shouldn't if you prepared
properly) then fine tune it (fine-granular optimizations). But
compilers these days are quite good at doing these optimizations for
you, so only "try" your tweaks if everything else fails (which it
shouldn't have, if you planned properly). Also, prepare for
optimizations by building proper interfaces (like making custome
interfaces for everything, including data types.. imagine that coding
is all done, but you realize that using int instead long for a whole
section of code will increase speed by a factor of 2 without breaking
the code... do you want to make a 1 line change or ... you get the
picture).

Nov 14 '05 #2
ni*************@yahoo.com wrote:

Below you will see an example of a nested conditional expression
that this colleague of mine loves. He claims that it is more
efficient that a multi-level if-else-if structure. Moreover, our
complexity analyzer tool supposedly does not pick it up. Is it
really more efficient? Personally I find this coding style
extremely cryptic, misleading and error-prone.

I believe that I have removed all traces of proprietary-ness from this
coding example by multiple text substitutions.
.... snip ...

After putting some decent indentation in (see sig below) you have:
printf(" ==> %s, Type %02X \n",
(code == QWER ? "QWER":
code == TYUI ? "TYUI":
code == ASDF ? "ASDF":
code == GHJK ? "GHJK":
code == ZXCV ? "ZXCV":
code == BNML ? "BNML": "????"),
type);


The other choice here is a temporary, and an if else chain:

char *tmp;

if (code == QWER) tmp = "QWER";
else if (code == TYUI) tmp = "TYUI";
else if (code == ASDF) tmp = "ASDF";
else if (code == GHJK) tmp = "GHJK";
else if (code == ZXCV) tmp = "ZXCV";
else if (code == BNML) tmp = "BNML";
else tmp = "????";
printf(" ==> %s, Type %02X \n", tmp, type);

Now, which is cleaner and more readable? Ignoring efficiency, I
think your colleague is doing just fine in this case. There are
few places where I would use the ? operator, yet this is one of
them. I would, however, probably isolate it in a routine such as:

char *typetostring(enum type t);

which would allow

printf(" ==> %s, Type %02X \n", typetostring(code), type);

You still have the temporary, it is just effected by the function
return value. However you can reuse the translation routine if
needed elsewhere.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 14 '05 #3

CBFalconer wrote:
ni*************@yahoo.com wrote:

Below you will see an example of a nested conditional expression
that this colleague of mine loves. He claims that it is more
efficient that a multi-level if-else-if structure. Moreover, our
complexity analyzer tool supposedly does not pick it up. Is it
really more efficient? Personally I find this coding style
extremely cryptic, misleading and error-prone.

I believe that I have removed all traces of proprietary-ness from this coding example by multiple text substitutions.


... snip ...

After putting some decent indentation in (see sig below) you have:
printf(" ==> %s, Type %02X \n",
(code == QWER ? "QWER":
code == TYUI ? "TYUI":
code == ASDF ? "ASDF":
code == GHJK ? "GHJK":
code == ZXCV ? "ZXCV":
code == BNML ? "BNML": "????"),
type);


The other choice here is a temporary, and an if else chain:

char *tmp;

if (code == QWER) tmp = "QWER";
else if (code == TYUI) tmp = "TYUI";
else if (code == ASDF) tmp = "ASDF";
else if (code == GHJK) tmp = "GHJK";
else if (code == ZXCV) tmp = "ZXCV";
else if (code == BNML) tmp = "BNML";
else tmp = "????";
printf(" ==> %s, Type %02X \n", tmp, type);

Now, which is cleaner and more readable? Ignoring efficiency, I
think your colleague is doing just fine in this case. There are
few places where I would use the ? operator, yet this is one of
them. I would, however, probably isolate it in a routine such as:


I personally would never nest ternary : ? opeartors like this
(especially never putting the whole thing inside a printf argument!).
If statements are less error prone and in this case, there really is no
reason to use :? operators (count the difference in number of
lines???).

Nov 14 '05 #4


Luke Wu wrote:

I personally would never nest ternary : ? opeartors like this
(especially never putting the whole thing inside a printf argument!).
If statements are less error prone and in this case, there really is no
reason to use :? operators (count the difference in number of
lines???).


State your preference:

hand_type = is_straight
? is_flush ? STRAIGHT_FLUSH : STRAIGHT
: is_flush ? FLUSH : NOTHING;

vs.

if (is_straight) {
if (is_flush) {
hand_type = STRAIGHT_FLUSH;
}
else {
hand_type = STRAIGHT;
}
}
else {
if (is_flush) {
hand_type = FLUSH;
}
else {
hand_type = NOTHING;
}
}

Neither is "righter" or "wronger" than the other, and
both clarity and beauty lie in the eye of the beholder.
Still, to my eye the first is preferable.

--
Er*********@sun.com

Nov 14 '05 #5
On 1/31/05 10:20 AM, in article ct**********@news1brm.Central.Sun.COM, "Eric
Sosman" <er*********@sun.com> wrote:


Luke Wu wrote:

I personally would never nest ternary : ? opeartors like this
(especially never putting the whole thing inside a printf argument!).
If statements are less error prone and in this case, there really is no
reason to use :? operators (count the difference in number of
lines???).


State your preference:

hand_type = is_straight
? is_flush ? STRAIGHT_FLUSH : STRAIGHT
: is_flush ? FLUSH : NOTHING;

vs.

if (is_straight) {
if (is_flush) {
hand_type = STRAIGHT_FLUSH;
}
else {
hand_type = STRAIGHT;
}
}
else {
if (is_flush) {
hand_type = FLUSH;
}
else {
hand_type = NOTHING;
}
}

Neither is "righter" or "wronger" than the other, and
both clarity and beauty lie in the eye of the beholder.
Still, to my eye the first is preferable.


Debugging is much easier in the latter. Try to set a breakpoint on the
ternary version.

Nov 14 '05 #6


Gregory Dean wrote:
On 1/31/05 10:20 AM, in article ct**********@news1brm.Central.Sun.COM, "Eric
Sosman" <er*********@sun.com> wrote:


Luke Wu wrote:
I personally would never nest ternary : ? opeartors like this
(especially never putting the whole thing inside a printf argument!).
If statements are less error prone and in this case, there really is no
reason to use :? operators (count the difference in number of
lines???).


State your preference:

hand_type = is_straight
? is_flush ? STRAIGHT_FLUSH : STRAIGHT
: is_flush ? FLUSH : NOTHING;

vs.

if (is_straight) {
if (is_flush) {
hand_type = STRAIGHT_FLUSH;
}
else {
hand_type = STRAIGHT;
}
}
else {
if (is_flush) {
hand_type = FLUSH;
}
else {
hand_type = NOTHING;
}
}

Neither is "righter" or "wronger" than the other, and
both clarity and beauty lie in the eye of the beholder.
Still, to my eye the first is preferable.

Debugging is much easier in the latter. Try to set a breakpoint on the
ternary version.


(1) No problem, if you'll let me choose a debugger
that can set breakpoints at arbitrary machine instructions.

(2) Try to set a breakpoint in the latter form, after
an optimizing compiler has transmogrified the code and
generated the same instructions as for the former form.

(3) Debugging is inferior to inspection, in the sense
that a debugger can (at best) show you things that have
actually happened, while inspection can drive assertions
about all the things that can and cannot happen. I feel
that the former is easier to inspect than the latter, hence
easier to prove things about, hence less likely have bugs
in the first place!

(4) Debuggers are like crutches: When you need them
you do in fact need them, but you will never progress as
well as when you can do without them.

(5) -- no, I'm starting to rant. Again ...

--
Er*********@sun.com

Nov 14 '05 #7
Eric Sosman wrote:
Gregory Dean wrote:
On 1/31/05 10:20 AM, in article ct**********@news1brm.Central.Sun.COM, "Eric Sosman" <er*********@sun.com> wrote:


Luke Wu wrote:

I personally would never nest ternary : ? opeartors like this
(especially never putting the whole thing inside a printf argument!).If statements are less error prone and in this case, there really is noreason to use :? operators (count the difference in number of
lines???).

State your preference:

hand_type = is_straight
? is_flush ? STRAIGHT_FLUSH : STRAIGHT
: is_flush ? FLUSH : NOTHING;

vs.

if (is_straight) {
if (is_flush) {
hand_type = STRAIGHT_FLUSH;
}
else {
hand_type = STRAIGHT;
}
}
else {
if (is_flush) {
hand_type = FLUSH;
}
else {
hand_type = NOTHING;
}
}

Neither is "righter" or "wronger" than the other, and
both clarity and beauty lie in the eye of the beholder.
Still, to my eye the first is preferable.
Yes, they are both "right," but the question is whether or not people
"accept" a method as being clear. In the real world, we don't keep our
code to ourselves (only in the fake world we do that), we share it and
allow others to understand it. I am pretty sure the people who find
the IF STATEMENTS "appropriate" are a superset of the ones that find
the nested CONDITIONALS "appropriate." In a software engineering
team, it's better to aim for the superset.

If you're only coding alongside seasoned veterans, without any junior
programmers, then the two sets are probably the same and you will have
no problem.

Debugging is much easier in the latter. Try to set a breakpoint on the ternary version.


(1) No problem, if you'll let me choose a debugger
that can set breakpoints at arbitrary machine instructions.

Do you have the luxury of choosing IDEs where you work? What if someone
else wrote the code and tested it for an IDE that doesn't offer the
features that you want? So your debugger has to conform to your code,
instead of your code being more universally debuggable? Source-level
debugging doesn't guarantee anything about machine instructions
(AFAIK).
(2) Try to set a breakpoint in the latter form, after
an optimizing compiler has transmogrified the code and
generated the same instructions as for the former form.
You are assuming that the ternary form doesn't need optimizing and that
the IF form, when optimized, produces the same code as the ternary form
(and otherwize creates more machine instructions). In fact, a friend of
mine who is a compiler writer told me that compilers he has written
would optimize the IF's better than the deeply nested ternaries.

You can always turn optimization off to debug a section of code you
know will be heavily optimized.
(3) Debugging is inferior to inspection, in the sense
that a debugger can (at best) show you things that have
actually happened, while inspection can drive assertions
about all the things that can and cannot happen.
You are comparing apples to organges. People don't pick debugging OVER
inspection or vice versa. The two happen at different phases and deal
with different problems. We should code to best satisfy all phases of
development/debugging, not one over the other.
I feel
that the former is easier to inspect than the latter, hence
easier to prove things about, hence less likely have bugs
in the first place!
IF statements are better for code inspections than DEEPLY NESTED
conditional ternaries. IF statements allow for braces to surround
different blocks that correspond to different conditions. Say if you
use extended bracing, you can draw lines from the top brace of every
block to the bottom brace of every block (in coloured pencils or
visually). This give so much more visibility than nested ternary
operators.

I like how you made the IF statements look overly expensive(with
brackets) while making the ternary statements look very clean in your
presentation above.

(4) Debuggers are like crutches: When you need them
you do in fact need them, but you will never progress as
well as when you can do without them.
I see, so you're that famous programmer I read about in magazines that
never needed debuggers. That means you're a PERFECT software engineer
and a very LUCKY software engineer that only ran into code written by
other PERFECT software engineers.
(5) -- no, I'm starting to rant. Again ...
I might be guilty of the same. I see no problem in the ternary
conditionals, but I work with a lot of beginner programmers (hardware
guys who are programming for the sake of controlling their hardware),
so for me the "superset" has far more members than the "subset."
--
Er*********@sun.com


Nov 14 '05 #8


Big K wrote:
Eric Sosman wrote:
Gregory Dean wrote:
On 1/31/05 10:20 AM, in article
ct**********@news1brm.Central.Sun.COM, "Eric
Sosman" <er*********@sun.com> wrote:

Luke Wu wrote:
>I personally would never nest ternary : ? opeartors like this
>(especially never putting the whole thing inside a printf
argument!).
If statements are less error prone and in this case, there really
is no
reason to use :? operators (count the difference in number of
>lines???).

State your preference:

hand_type = is_straight
? is_flush ? STRAIGHT_FLUSH : STRAIGHT
: is_flush ? FLUSH : NOTHING;

vs.

if (is_straight) {
if (is_flush) {
hand_type = STRAIGHT_FLUSH;
}
else {
hand_type = STRAIGHT;
}
}
else {
if (is_flush) {
hand_type = FLUSH;
}
else {
hand_type = NOTHING;
}
}

Neither is "righter" or "wronger" than the other, and
both clarity and beauty lie in the eye of the beholder.
Still, to my eye the first is preferable.
Yes, they are both "right," but the question is whether or not people
"accept" a method as being clear. In the real world, we don't keep our
code to ourselves (only in the fake world we do that), we share it and
allow others to understand it. I am pretty sure the people who find
the IF STATEMENTS "appropriate" are a superset of the ones that find
the nested CONDITIONALS "appropriate." In a software engineering
team, it's better to aim for the superset.

If you're only coding alongside seasoned veterans, without any junior
programmers, then the two sets are probably the same and you will have
no problem.
If we eliminate from C all the things some people find
confusing, what will remain? The traffic in this newsgroup
shows that people are confused by arrays, by pointers, by
floating-point arithmetic, by much of <stdio.h> (printf()
makes lots of trouble, scanf() even more), by all of <ctype.h>,
by structs, by functions with prototypes, by functions without
prototypes, by variable-length argument lists, and by main().

Purging C of all these (and of the many other confusions
I haven't listed; these are off-the-top-of-my head topics)
would leave a language that might be named "C minus" but would
certainly not merit so high a mark ...
Debugging is much easier in the latter. Try to set a breakpoint on
the
ternary version.


(1) No problem, if you'll let me choose a debugger
that can set breakpoints at arbitrary machine instructions.


Do you have the luxury of choosing IDEs where you work? What if someone
else wrote the code and tested it for an IDE that doesn't offer the
features that you want? So your debugger has to conform to your code,
instead of your code being more universally debuggable? Source-level
debugging doesn't guarantee anything about machine instructions
(AFAIK).


Are you arguing that debuggers should not have capabilities
not shared by all other debuggers? That is, that there should
be just one Ur-debugger?
(2) Try to set a breakpoint in the latter form, after
an optimizing compiler has transmogrified the code and
generated the same instructions as for the former form.


You are assuming that the ternary form doesn't need optimizing and that
the IF form, when optimized, produces the same code as the ternary form
(and otherwize creates more machine instructions).


No; I'm assuming that some compiler somewhere might generate
the same code for both forms.
In fact, a friend of
mine who is a compiler writer told me that compilers he has written
would optimize the IF's better than the deeply nested ternaries.
Strange; the latter should be easier. For starters,
there's only one assignment target, hence no need to "notice"
that the four targets in the `if' form are in fact the same.

Perhaps your friend may have been referring to code like

#define max2(a,b) ((a) > (b) ? (a) : (b))
#define max4(a,b,c,d) max2(max2((a),(b)), \
max2((c),(d)))

.... which I would most definitely not recommend; the apparent
simplicity conceals a surprisingly voluminous expansion, with
lots of common sub-expressions a compiler might need to struggle
to eliminate.
You can always turn optimization off to debug a section of code you
know will be heavily optimized.
.... at which point you are no longer debugging the actual code,
but a sort of proxy for it. I've debugged plenty of problems
that only showed up after optimization, that is, problems that
simply vanished when optimization was turned down or off. "Test
what you fly; fly what you test."
(3) Debugging is inferior to inspection, in the sense
that a debugger can (at best) show you things that have
actually happened, while inspection can drive assertions
about all the things that can and cannot happen.


You are comparing apples to organges. People don't pick debugging OVER
inspection or vice versa. The two happen at different phases and deal
with different problems. We should code to best satisfy all phases of
development/debugging, not one over the other.


Different development activities have different goals and
are sometimes in conflict. It is not always possible to "best
satisfy" all of them; compromises are required.

However, I'll still maintain that it's better to be able
to prove things about a section of code than to run a bunch
of test cases through it and say "Well, nothing broke. Yet."
I feel
that the former is easier to inspect than the latter, hence
easier to prove things about, hence less likely have bugs
in the first place!


IF statements are better for code inspections than DEEPLY NESTED
conditional ternaries.


Proof by assertion. (You're in good company; Edsger W.
Dijkstra did a lot of important work, but is probably best
known for just such a proof.)
IF statements allow for braces to surround
different blocks that correspond to different conditions. Say if you
use extended bracing, you can draw lines from the top brace of every
block to the bottom brace of every block (in coloured pencils or
visually). This give so much more visibility than nested ternary
operators.
If you feel like it, you can do the same with ternaries:

hand_type
= is_flush
? is_straight
? STRAIGHT_FLUSH
: FLUSH
: is_straight
? STRAIGHT
: NOTHING;

.... and you can even throw in a few levels of parentheses if
you want them.
I like how you made the IF statements look overly expensive(with
brackets) while making the ternary statements look very clean in your
presentation above.
Observation #1: Didn't you just get through saying
you *liked* all those braces?

Observation #2: Did you just describe the ternary
formulation as "very clean?" My point, exactly.
(4) Debuggers are like crutches: When you need them
you do in fact need them, but you will never progress as
well as when you can do without them.


I see, so you're that famous programmer I read about in magazines that
never needed debuggers. That means you're a PERFECT software engineer
and a very LUCKY software engineer that only ran into code written by
other PERFECT software engineers.


Excuse me, but what justifies this insult? Did I not say
that "When you need them you do in fact need them?" Yes, I
did. Did I claim perfection? No, I did not. Back off.
I might be guilty of the same. I see no problem in the ternary
conditionals, but I work with a lot of beginner programmers (hardware
guys who are programming for the sake of controlling their hardware),
so for me the "superset" has far more members than the "subset."


Clarity of expression is not achieved through baby talk.

--
Er*********@sun.com

Nov 14 '05 #9

ni*************@yahoo.com wrote:
Below you will see an example of a nested conditional expression that
this colleague of mine loves. He claims that it is more efficient that a multi-level if-else-if structure.


Make him show you the profiling data he gathered that allowed him to
reach this conclusion.

Terse code doesn't necessarily equate to fast or efficient code. In
fact, I can think of cases the opposite is true; unrolling a loop
results in more verbosity, but can improve perfomance. OTOH, a terse
recursive algorithm can incur significant overhead compared to a more
verbose, iterative equivalent (fibonacci or factorials, for example).

Having said that, it's possible that nested ternary expressions are
faster/smaller than an equivalent if-else structure, but you'd have to
profile the two versions to know for sure.

Nov 14 '05 #10
Eric Sosman wrote:
Big K wrote:
Eric Sosman wrote:
Gregory Dean wrote:

On 1/31/05 10:20 AM, in article
ct**********@news1brm.Central.Sun.COM, "Eric
Sosman" <er*********@sun.com> wrote:

>Luke Wu wrote:
>
>
>>I personally would never nest ternary : ? opeartors like this
>>(especially never putting the whole thing inside a printf


argument!).
>>If statements are less error prone and in this case, there
really

is no
>>reason to use :? operators (count the difference in number of
>>lines???).
>
> State your preference:
>
>hand_type = is_straight
> ? is_flush ? STRAIGHT_FLUSH : STRAIGHT
> : is_flush ? FLUSH : NOTHING;
>
>vs.
>
>if (is_straight) {
> if (is_flush) {
> hand_type = STRAIGHT_FLUSH;
> }
> else {
> hand_type = STRAIGHT;
> }
>}
>else {
> if (is_flush) {
> hand_type = FLUSH;
> }
> else {
> hand_type = NOTHING;
> }
>}
>
>Neither is "righter" or "wronger" than the other, and
>both clarity and beauty lie in the eye of the beholder.
>Still, to my eye the first is preferable.


Yes, they are both "right," but the question is whether or not people "accept" a method as being clear. In the real world, we don't keep our code to ourselves (only in the fake world we do that), we share it and allow others to understand it. I am pretty sure the people who find the IF STATEMENTS "appropriate" are a superset of the ones that find the nested CONDITIONALS "appropriate." In a software engineering
team, it's better to aim for the superset.

If you're only coding alongside seasoned veterans, without any junior programmers, then the two sets are probably the same and you will have no problem.


If we eliminate from C all the things some people find
confusing, what will remain? The traffic in this newsgroup
shows that people are confused by arrays, by pointers, by
floating-point arithmetic, by much of <stdio.h> (printf()
makes lots of trouble, scanf() even more), by all of <ctype.h>,
by structs, by functions with prototypes, by functions without
prototypes, by variable-length argument lists, and by main().

We're talking about two different ways to do the same thing by an
actual developer (read original post), not about the mistakes made by
people learning the language. I guess the DEEP TERNARY NESTING vs.
MULTILEVEL IF is just a difference of opinion, let's leave it at that.
Purging C of all these (and of the many other confusions
I haven't listed; these are off-the-top-of-my head topics)
would leave a language that might be named "C minus" but would
certainly not merit so high a mark ...
Once again, this is not a discussion about "purging" ternary operators
from the language and forcing developers to use IF statemetns. We're
talking about a solution to a problem (presented by the original
poster), that can be solved by NESTED TERNARIES or MULTILEVEL IF
statements. Nobody is talking about removing actual features from the
language. If you read the original post, you will see that the
individual was "at first glance" confused by the use of nested
ternaries. He also mentioned that certain tools his company used
couldn't recognize the nested ternaries, while it recognized the
multilevel IFs. I don't know where you go the idea that I wanted to
"purge" features from the language. Ternaries are awesome, but their
use in deep nesting can cause problems to less experienced developers,
optimizers, debuggers, complexity analyzers, etc (which was the subject
of the original post- have a look).

I am not bashing ternary operators or you're use of them. You probably
use it in a much clearer way than in the code the OP encountered,
which is fine. >>>Debugging is much easier in the latter. Try to set a breakpoint
on

the
ternary version.

(1) No problem, if you'll let me choose a debugger
that can set breakpoints at arbitrary machine instructions.
Do you have the luxury of choosing IDEs where you work? What if someone else wrote the code and tested it for an IDE that doesn't offer the
features that you want? So your debugger has to conform to your code, instead of your code being more universally debuggable? Source-level debugging doesn't guarantee anything about machine instructions
(AFAIK).


Are you arguing that debuggers should not have capabilities
not shared by all other debuggers? That is, that there should
be just one Ur-debugger?

No, but if you read the concerns of the OP, you will notice that his
tools had trouble recognizing the ternary conditionals AND he was
dealing with code developed by someone else. If you have a really
awesome debugger that lets you set machine level breakpoints while
stepping through source level code, then I guess this is a non-issue. (2) Try to set a breakpoint in the latter form, after
an optimizing compiler has transmogrified the code and
generated the same instructions as for the former form.
You are assuming that the ternary form doesn't need optimizing and that
the IF form, when optimized, produces the same code as the ternary form (and otherwize creates more machine instructions).


No; I'm assuming that some compiler somewhere might generate
the same code for both forms.

Then what did you mean by this comment:
---
(2) Try to set a breakpoint in the latter form [with IFs], after
an optimizing compiler has transmogrified the code and
generated the same instructions as for the former form.
---
If you meant that a compiler somewhere might generate the same code for
both forms, then how does your comment above (2) support nested
ternaries?
[Not insulting, I am just confused]

In fact, a friend of
mine who is a compiler writer told me that compilers he has written
would optimize the IF's better than the deeply nested ternaries.
Strange; the latter should be easier. For starters,
there's only one assignment target, hence no need to "notice"
that the four targets in the `if' form are in fact the same.

Different of opinion among different people. Let's leave it there.
Perhaps your friend may have been referring to code like

#define max2(a,b) ((a) > (b) ? (a) : (b))
#define max4(a,b,c,d) max2(max2((a),(b)), \
max2((c),(d)))

... which I would most definitely not recommend; the apparent
simplicity conceals a surprisingly voluminous expansion, with
lots of common sub-expressions a compiler might need to struggle
to eliminate.
Nope, wasn't referring to that.
You can always turn optimization off to debug a section of code you
know will be heavily optimized.
... at which point you are no longer debugging the actual code,
but a sort of proxy for it. I've debugged plenty of problems
that only showed up after optimization, that is, problems that
simply vanished when optimization was turned down or off. "Test
what you fly; fly what you test."

I was responding to your comment (2). A compiler is free to optimize
either form, so I had no clue what your comment (2) was trying to
convey. Of course you should turn optimization on again after you have
found the fault with the debugger (that's if you had to resort to
turning it off in the first place, which is always a last-hope method).
NASA's mantra "test what you fly; fly waht you test" is posted above
the whiteboard beside me. But what is wrong with doing intermediate
tests on proxies to find a fault, then doing thorough tests on the real
thing afterwards? (3) Debugging is inferior to inspection, in the sense
that a debugger can (at best) show you things that have
actually happened, while inspection can drive assertions
about all the things that can and cannot happen.
You are comparing apples to organges. People don't pick debugging OVER
inspection or vice versa. The two happen at different phases and deal with different problems. We should code to best satisfy all phases of development/debugging, not one over the other.


Different development activities have different goals and
are sometimes in conflict. It is not always possible to "best
satisfy" all of them; compromises are required.

However, I'll still maintain that it's better to be able
to prove things about a section of code than to run a bunch
of test cases through it and say "Well, nothing broke. Yet."


Code inspections don't catch all bugs, neither does debugging. There is
no "better" method. You try to catch bugs as early as possible, and
you make every phase in the development cycle as robust as possible-
you can't make compromises. Everything must be taken seriously, there
are no preferences.
I feel
that the former is easier to inspect than the latter, hence
easier to prove things about, hence less likely have bugs
in the first place!
Difference of opinion. But realize that you can't rely solely on code
inspections.

IF statements are better for code inspections than DEEPLY NESTED
conditional ternaries.


Proof by assertion. (You're in good company; Edsger W.
Dijkstra did a lot of important work, but is probably best
known for just such a proof.)

Proof? It's an opinion that was a response to your opinion.
IF statements allow for braces to surround
different blocks that correspond to different conditions. Say if you use extended bracing, you can draw lines from the top brace of every block to the bottom brace of every block (in coloured pencils or
visually). This give so much more visibility than nested ternary
operators.
If you feel like it, you can do the same with ternaries:

hand_type
= is_flush
? is_straight
? STRAIGHT_FLUSH
: FLUSH
: is_straight
? STRAIGHT
: NOTHING;

... and you can even throw in a few levels of parentheses if
you want them.

Difference of opinion.
I like how you made the IF statements look overly expensive(with
brackets) while making the ternary statements look very clean in your presentation above.
Observation #1: Didn't you just get through saying
you *liked* all those braces?

I like extended braces (read my comments again).
Observation #2: Did you just describe the ternary
formulation as "very clean?" My point, exactly.

I said "look very clean" in the superficial sense. That says nothing
about how easy it is to understand the code, or how well tools can
deal with it. (4) Debuggers are like crutches: When you need them
you do in fact need them, but you will never progress as
well as when you can do without them.
I see, so you're that famous programmer I read about in magazines that never needed debuggers. That means you're a PERFECT software engineer and a very LUCKY software engineer that only ran into code written by other PERFECT software engineers.


Excuse me, but what justifies this insult? Did I not say
that "When you need them you do in fact need them?" Yes, I
did. Did I claim perfection? No, I did not. Back off.

Read (4) again. It was in response to another poster and the OP who
were obviously concerned about debuggers and other tools. In (4) it
"sounded" like you were saying that people who "needed" debuggers were
inferior somehow. Maybe I took it the wrong way, but then again, you
did take my joke as an "insult" too.
I might be guilty of the same. I see no problem in the ternary
conditionals, but I work with a lot of beginner programmers (hardware guys who are programming for the sake of controlling their hardware), so for me the "superset" has far more members than the "subset."
Clarity of expression is not achieved through baby talk.

Clarity is not measured in lines of code, and isn't the only important
facet of software development (even though I think the IFs are more
clear). If you are referring to the fact that some programmers make
their code extra "babyish" to allow beginners to understand it, then
what's wrong with that? Like you said, the two methods can be optimized
to the same machine instructions, so why not make the code extra
"clear" to the people who are most likely to trip over it? Tools matter
too, and OP obviously had some issues with the nested ternaries. Let's
leave opinions out of it, and concentrate on the issues the OP had.
Deal?
--
Er*********@sun.com


There is no reason to continue this discussion, since opinions are just
that, opinions (I appologize for trying to assert my opinion).

Nov 14 '05 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.