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

Discussion in 'C Programming' started by nimmi_srivastav@yahoo.com, Jan 30, 2005.

  1. Guest

    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);
    }
    , Jan 30, 2005
    #1
    1. Advertising

  2. Guest

    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).
    , Jan 30, 2005
    #2
    1. Advertising

  3. CBFalconer Guest

    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
    CBFalconer, Jan 30, 2005
    #3
  4. Luke Wu Guest

    CBFalconer wrote:
    > 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???).
    Luke Wu, Jan 30, 2005
    #4
  5. Eric Sosman Guest

    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.

    --
    Eric Sosman, Jan 31, 2005
    #5
  6. Gregory Dean Guest

    On 1/31/05 10:20 AM, in article ctlic0$ffm$, "Eric
    Sosman" <> 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.
    Gregory Dean, Jan 31, 2005
    #6
  7. Eric Sosman Guest

    Gregory Dean wrote:
    > On 1/31/05 10:20 AM, in article ctlic0$ffm$, "Eric
    > Sosman" <> 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 ...

    --
    Eric Sosman, Jan 31, 2005
    #7
  8. Big K Guest

    Eric Sosman wrote:
    > Gregory Dean wrote:
    > > On 1/31/05 10:20 AM, in article

    ctlic0$ffm$, "Eric
    > > Sosman" <> 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.

    > >
    > > 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."
    >
    > --
    >
    Big K, Feb 2, 2005
    #8
  9. Eric Sosman Guest

    Big K wrote:
    > Eric Sosman wrote:
    >
    >>Gregory Dean wrote:
    >>
    >>>On 1/31/05 10:20 AM, in article

    >
    > ctlic0$ffm$, "Eric
    >
    >>>Sosman" <> 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.

    --
    Eric Sosman, Feb 2, 2005
    #9
  10. Guest

    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.
    , Feb 2, 2005
    #10
  11. Big K Guest

    Eric Sosman wrote:
    > Big K wrote:
    > > Eric Sosman wrote:
    > >
    > >>Gregory Dean wrote:
    > >>
    > >>>On 1/31/05 10:20 AM, in article

    > >
    > > ctlic0$ffm$, "Eric
    > >
    > >>>Sosman" <> 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?
    >
    > --
    >


    There is no reason to continue this discussion, since opinions are just
    that, opinions (I appologize for trying to assert my opinion).
    Big K, Feb 2, 2005
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    6
    Views:
    557
  2. GeoTrail
    Replies:
    4
    Views:
    2,380
    gswork
    Jan 16, 2004
  3. Hal Vaughan
    Replies:
    1
    Views:
    407
    Mark Space
    Jan 23, 2008
  4. rantingrick
    Replies:
    44
    Views:
    1,146
    Peter Pearson
    Jul 13, 2010
  5. Joe Snodgrass

    Good idea, bad execution

    Joe Snodgrass, Nov 13, 2010, in forum: Java
    Replies:
    19
    Views:
    573
    Joe Snodgrass
    Nov 22, 2010
Loading...

Share This Page