in reply to Re: Nested ternaries
in thread Nested ternaries

Beautiful, I was having a problem testing all cases, which quickly showed the flaw in my logic, and I believe the and was throwing off the ternary - it has leftward associativity while ?: is rightward. The following changes looks like it will do what I want:

sub tt { my( $cookie, $param ) = @_; my $str = '(' . (defined $cookie ? $cookie : 'undef'); $str .= ',' . (defined $param ? $param : 'undef') . "):\t"; $str .= $cookie # I quickly realized it was necessary to test this here ? ( ( $param and $param =~ /^\d{1,2}$/ ) ? $param : $cookie +) # and I had to place a few more parens #: ( $param ? ($param and $param =~ /^\d{1,2}$/) : 5 ); # UPDATE: the above line was horribly translated from Grandf +athers. # It is corrected below, which also works when the same nest +ed # ternary idea (substituting /^\w{1,6}$/ for example) is use +d to # parse textual data. : ( ( $param and $param =~ /^\d{1,2}$/ ) ? $param : 5 ); # END UPDATE $str .= "\n"; return $str; } print tt( 4, 3 ); print tt( 4, 333 ); print tt( 444, 333 ); print tt( 2, undef ); print tt( undef, 1 ); print tt( undef, undef );

Prints:

(4,3): 3 (4,333): 4 (444,333): 444 # famous last words, but "this can never happen" ; +) (2,undef): 2 (undef,1): 1 (undef,undef): 5

++Grandfather, terse though your reply was (lacking explanation but sufficient code to guide me to the solution), I thank you for that quick sanity check.



--chargrill
$/ = q#(\w)# ; sub sig { print scalar reverse join ' ', @_ } + sig map { s$\$/\$/$\$2\$1$g && $_ } split( ' ', ",erckha rlPe erthnoa stJu +" );

Replies are listed 'Best First'.
Re^3: Nested ternaries
by GrandFather (Saint) on Feb 16, 2006 at 01:39 UTC

    I decided the code was sufficient to stand on its own - seems that it did. Glad you liked it :)


    DWIM is Perl's answer to Gödel
Re^3: Nested ternaries
by chargrill (Parson) on Feb 22, 2006 at 17:40 UTC

    Continually irritated at the ugliness of the nested ternary once placed back into my code:

    $scheme = $cookies{'skin'} ? ( ( param( 'scheme' ) and param( 'scheme' ) =~ /^\w{1,6}$/ ) ? param( 'scheme' ) : $cookies{'skin'}->value ) : ( ( param( 'scheme' ) and param( 'scheme' ) =~ /^\w{1,6}$/ ) ? param( 'scheme' ) : 'default' );

    Along with an offline suggestion from liverpole of an operator (||=) I had forgotten yields the following test code:

    use strict; use warnings; sub ttw { my( $cookie, $param ) = @_; my $str = '(' . (defined $cookie ? $cookie : 'undef'); $str .= ',' . (defined $param ? $param : 'undef') . "):\t"; $str .= $cookie ||= $param && $param =~ /^\w{1,6}$/ ? $param : 'defa +ult'; $str .= "\n"; return $str; } sub ttd { my( $cookie, $param ) = @_; my $str = '(' . (defined $cookie ? $cookie : 'undef'); $str .= ',' . (defined $param ? $param : 'undef') . "):\t"; $str .= $cookie ||= $param && $param =~ /^\d{1,2}$/ ? $param : 5; $str .= "\n"; return $str; } print ttw( 'yellow', 'blue' ); print ttw( 'green', undef ); print ttw( undef, 'teal' ); print ttw( undef, 'chartreuse' ); print ttw( undef, undef ); print ttd( undef, undef ); print ttd( 4, undef); print ttd( 444, undef); print ttd( undef, 3); print ttd( undef, 333); print ttd( 6, 7);

    ... which prints:

    (yellow,blue): yellow (green,undef): green (undef,teal): teal (undef,chartreuse): default (undef,undef): default (undef,undef): 5 (4,undef): 4 (444,undef): 444 (undef,3): 3 (undef,333): 5 (6,7): 6

    And finally the finished code re-worked into my original CGI looks much more succint:

    $scheme = $cookies{'skin'} ||= param( 'scheme' ) && param( 'scheme' ) =~ /^\w{1,6$/ ? param( 'scheme' ) : 'default';

    ... but doesn't work. So I try:

    $scheme = $cookies{'skin'}->value ||= param( 'scheme' ) && param( 'scheme' ) =~ /^\w{1,6$/ ? param( 'scheme' ) : 'default';

    ... which throws an error, Can't modify non-lvalue subroutine call at /path/to/viewer.cgi line 74. And now I can't imagine a way to re-work the ||= operator into my code. Which leaves me with my original, working, ugly version.

    I guess my point is that it's fine to simplify code for the purposes of testing, but be wary of shortcuts (golfing) taken to eliminate what might appear to be unnecessary syntax in the test version.



    --chargrill
    $/ = q#(\w)# ; sub sig { print scalar reverse join ' ', @_ } + sig map { s$\$/\$/$\$2\$1$g && $_ } split( ' ', ",erckha rlPe erthnoa stJu +" );