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-08-2012 at 11:59 PM.

  2. #2
    Pedantic Curmudgeon Weedpacket's Avatar
    Join Date
    Aug 2002
    Location
    General Contact Unit "Coping Mechanism"
    Posts
    22,313
    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
    14,478
    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.
    "Well done....Consciousness to sarcasm in five seconds!" ~ Terry Pratchett, Night Watch

    How to Ask Questions the Smart Way (not affiliated with this site, but well worth reading)

    My Blog
    cwrBlog: simple, no-database PHP blogging framework

  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 01:09 AM.

  7. #7
    Pedantic Curmudgeon Weedpacket's Avatar
    Join Date
    Aug 2002
    Location
    General Contact Unit "Coping Mechanism"
    Posts
    22,313
    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 Contact Unit "Coping Mechanism"
    Posts
    22,313
    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 08: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
  •