ternary operator: "left" associativity?
Results 1 to 10 of 10

Thread: ternary operator: "left" associativity?

  1. #1
    Senior Member traq's Avatar
    Join Date
    Jun 2011
    Location
    so.Cal
    Posts
    949

    ternary operator: "left" associativity?

    Anyone feel like explaining this to me?

    I understand the concept of associativity with regards to mathmatical and assignment operators, but this is going right over my head (and making a whistling noise as it passes).
    I understand what is happening (the outcome); I don't understand how it is happening (the process):

    PHP Code:
    <?php
    echo (FALSE "a" FALSE "b" "c")."\n";
    echo (
    FALSE "a" TRUE  "b" "c")."\n";
    echo (
    TRUE  "a" FALSE "b" "c")."\n";
    echo (
    TRUE  "a" TRUE  "b" "c")."\n";

    /** Expected **|** Actual **
        c              c
        b              b
        a              b
        a              b
    */
    "Right" associativity (e.g., an assignment statement) evaluates like this:
    Code:
     $a =  $b = 42;
    ($a = ($b = 42))
    So... what does the "left" associativity of a ternary statement look like?
    Last edited by traq; 12-09-2012 at 12:59 AM.

  2. #2
    Pedantic Curmudgeon Weedpacket's Avatar
    Join Date
    Aug 2002
    Location
    General Systems Vehicle "Thrilled To Be Here"
    Posts
    21,911
    PHP Code:
    ($a $b $c) ? $d $e 
    Use $a to decide whether to use $b or $c when deciding whether to use $d or $e.

    Dumb, but that's how it was made.
    THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER
    FAQs! FAQs! FAQs! Most forums have them!
    Search - Debugging 101 - Collected Solutions - General Guidelines - Getting help at all

  3. #3
    Senior Member traq's Avatar
    Join Date
    Jun 2011
    Location
    so.Cal
    Posts
    949
    Ahh... thanks!

    I'm pretty sure I've run into this before, too - but I didn't know what was going on. Good to know I am not the crazy one (at least, not for this reason )

  4. #4
    High Energy Magic Dept. NogDog's Avatar
    Join Date
    Aug 2006
    Location
    Ankh-Morpork
    Posts
    13,986
    I always use parentheses when I combine ternary expressions like that, so when I come back to them later I don't have to remember how they work again.

    Well, actually, I no longer use ternary expressions except for very simple cases, as I'm more into readability now than I am into terseness.
    Please give us a simple answer, so that we don't have to think, because if we think, we might find answers that don't fit the way we want the world to be." ~ from Nation, by Terry Pratchett

    "But the main reason that any programmer learning any new language thinks the new language is SO much better than the old one is because hes a better programmer now!" ~ http://www.oreillynet.com/ruby/blog/...ck_to_p_1.html


    eBookworm.us

  5. #5
    Senior Member traq's Avatar
    Join Date
    Jun 2011
    Location
    so.Cal
    Posts
    949
    I try to use it only for if/else variable assignments.
    Since discovering this issue, I've resolved to use them only in simple cases (no more "nested" ternaries).

  6. #6
    Senior Member traq's Avatar
    Join Date
    Jun 2011
    Location
    so.Cal
    Posts
    949
    Just a flash. Take these (the constructs that don't work)
    PHP Code:
    echo (TRUE  "a" FALSE "b" "c")."\n"
    echo (
    TRUE  "a" TRUE  "b" "c")."\n"
    and indent them (as you normally would, if they were actual if{} else{} blocks). You'd get:
    PHP Code:
    //  (exaggerated indentation)
    echo (TRUE  
                
    "a" 
                
    FALSE 
                        
    "b" 
                        
    "c"); 
    echo (
    TRUE  
                
    "a" 
                 
    TRUE  
                        
    "b" :  
                        
    "c"); 
    see how it kinda has a "step-down" look to it?

    Invert the conditions (i.e., !condition) and switch the order of their (if true) / (if false) expressions. You'll end up indenting out, then indenting back in, like this:
    PHP Code:
    echo ( !TRUE ?
                !
    FALSE ?
                            
    "b":
                            
    "c":
                
    "a"
    );

    echo ( !
    TRUE ?
                !
    TRUE ?
                            
    "b":
                            
    "c":
                
    "a"
    ); 
    equivalent conditions, but it works as expected.

    Now, I'm not advocating using deeply nested ternaries everywhere. It's just a thorn in my paw when I can't get something to work that should work, dammit. So, just remember to always put new conditionals first, in the "if true" expression, and never in the "if false".
    PHP Code:
    echo (!TRUE  ? !FALSE "b" "c" "a")."\n"
    echo (!
    TRUE  ? !TRUE  "b" "c" "a")."\n"

    **********

    BTW Merry Christmas, everyone : )
    Last edited by traq; 12-25-2012 at 02:09 AM.

  7. #7
    Pedantic Curmudgeon Weedpacket's Avatar
    Join Date
    Aug 2002
    Location
    General Systems Vehicle "Thrilled To Be Here"
    Posts
    21,911
    Or parenthesise to override the associativity with a higher-precedence operator (namely the parentheses).
    THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER
    FAQs! FAQs! FAQs! Most forums have them!
    Search - Debugging 101 - Collected Solutions - General Guidelines - Getting help at all

  8. #8
    Senior Member traq's Avatar
    Join Date
    Jun 2011
    Location
    so.Cal
    Posts
    949
    yeah. both options are kinda kludgy, unfortunately. I don't think it's reasonable/practical to have to put conditions in a specific (unexplained!) order, or manually nest everything in parenthesis, to make it work.

  9. #9
    Pedantic Curmudgeon Weedpacket's Avatar
    Join Date
    Aug 2002
    Location
    General Systems Vehicle "Thrilled To Be Here"
    Posts
    21,911
    I know what you mean (hey, I've already said left-associativity was dumb!). For example, it would otherwise be quite tolerable for me to have
    PHP Code:
    $foo condition1 value1 :
           
    condition2 value2 :
           
    condition3 value3 :
           
    condition4 value4 value0
    with additional spacing to ensure the ? and : actually do line up.

    Reversing the conditionals or putting the parentheses in to fix the associativity give
    PHP Code:
    $foo condition1 value1 :
          (
    condition2 value2 :
          (
    condition3 value3 :
          (
    condition4 value4 value0)));

    $foo = !condition1 ?
           !
    condition2 ?
           !
    condition3 ?
           !
    condition4 value0 :
                         
    value4 
                         
    value3 
                         
    value2 
                         
    value1
    (I'm not advocating deeply-nested conditionals everywhere either, but the above is completely lucid compared to something like c1 ? c2 : c3 ? c4 ? c5 ? v3 : v4 : (c6 ? v5 : v6) : (c7 ? v7 : v4).)

    One thing I'll observe at this point - because I see a lot of code where the author has apparently gone to a lot of trouble to avoid it - is that if(condition ? test1 : test2) is legal and doesn't need to be written as if((condition && test1) || (!condition && test2)).
    Last edited by Weedpacket; 12-25-2012 at 09:22 PM.
    THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER
    FAQs! FAQs! FAQs! Most forums have them!
    Search - Debugging 101 - Collected Solutions - General Guidelines - Getting help at all

  10. #10
    Senior Member traq's Avatar
    Join Date
    Jun 2011
    Location
    so.Cal
    Posts
    949
    Quote Originally Posted by Weedpacket View Post
    ... if(condition ? test1 : test2) is legal and doesn't need to be written as if((condition && test1) || (!condition && test2)).
    wow - hadn't thought of that.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •