in reply to Re^2: Short form (ternary) if else
in thread Short form (ternary) if else

That's not correct. The ternary operator will generate some sort of value - what you do with that value is up to you. You could, for example, use it to create a boolean return value:

return defined $result ? 1 : 0;

You can also nest ternary operators. Say you wanted to compare two numbers and produce: 1 if the first number was bigger; 0 if they were the same; -1 if the second number was bigger:

my $cmp = $x > $y ? 1 : $x == $y ? 0 : -1;

-- Ken

Replies are listed 'Best First'.
Re^4: Short form (ternary) if else
by Marshall (Canon) on Feb 08, 2012 at 22:26 UTC
    This is the "spaceship" operator for comparing in a numeric sense:
    #!/usr/bin/perl -w use strict; my $x = 2; my $y = 3; my $cmp_result = $x <=> $y; print $cmp_result # -1
    Note: while naming variables the same as Perl key words is allowed (e.g. $cmp, (cmp is a key word), I personally try to avoid this).

    for comparison in a string context, use cmp:

    my $cmp_result = $stringX cmp $stringY;
    Update: As to the history, I have no idea why <=> is called the "spaceship" operator, but that is the common usage.
Re^4: Short form (ternary) if else
by gg48gg (Sexton) on Feb 08, 2012 at 22:35 UTC

    Ken, I really do understand the scope thing. I just screwed it up when I first posted. But given the correct scope...

    Are you saying that the below code should work?
    my $vxdg; (exists $vxdgs{$node}{$disk}) ? $vxdg=$vxdgs{$node}{$disk} : $vxdg="";
    or will it only work like:
    my $vxdg = exists $vxdgs{$node}{$disk} ? vxdgs{$node}{$disk} : '';

      Both will work (i.e. run without error) but the first form won't do what you're expecting due to operator precedence. The second form is preferable anyway because it is shorter, less complicated and easier to read. Take a look at the perlop manpage - under Conditional Operator for an explanation.

      I suggest you write some test code for yourself rather than just asking whether this or that code will or won't work. You can do this sort of thing on the commandline:

      ken@ganymede: ~/tmp $ perl -Mstrict -Mwarnings -E 'my $x = 1 ? 1 : 0; say $x;' 1 ken@ganymede: ~/tmp $ perl -Mstrict -Mwarnings -E 'my $x; 1 ? $x=1 : $x=0; say $x;' 0 ken@ganymede: ~/tmp $ perl -Mstrict -Mwarnings -E 'my $x; 1 ? ($x=1) : ($x=0); say $x;' 1 ken@ganymede: ~/tmp $

      -- Ken

        I'm surprised by this result:
        ken@ganymede: ~/tmp $ perl -Mstrict -Mwarnings -E 'my $x; 1 ? $x=1 : $x=0; say $x;' 0
        Do you know why $x becomes 0?

      If you want to see how Perl sees and parses your code (and in particular, via the  -p "extra parens, please" switch, how it interprets precedence), use the O and Deparse modules:

      >perl -wMstrict -MO=Deparse,-p -le "my ($node, $disk, %vxdgs) = (0, 0); my $vxdg; (exists $vxdgs{$node}{$disk}) ? $vxdg = $vxdgs{$node}{$disk} : $vxdg = ''; " BEGIN { $^W = 1; } BEGIN { $/ = "\n"; $\ = "\n"; } use strict 'refs'; (my($node, $disk, %vxdgs) = (0, 0)); my($vxdg); ((exists($vxdgs{$node}{$disk}) ? ($vxdg = $vxdgs{$node}{$disk}) : $vxd +g) = ''); -e syntax OK
      Ken's comments are "spot on".
      The second form is far preferable because it is just far more clear!

      There is however another "layer" of complexity to this question that you are probably not aware of....

      When testing for the existence of some value in a 2D hash, Perl will "autovivify" the first dimension(s) if it(they) doesn't exist already. The code below demonstrates this behavior. This can lead to some side-effects and strange results later.

      This statement:

      $var = $vxdg{$node}{$disk} //= '';
      creates the entire multi-dimensional key and assigns it the value of '' if it wasn't already defined. This '//=' operator is specific to Perl. It is like ||= except that it tests for "defined-ness" instead of "truth-ness". Whether or not this is a "good thing" or "not" depends upon the application.

      I'm just suggesting that you should be aware of what happens when testing for existence or "defined-ness" of multi-dimensional hash array values.

      #!/usr/bin/perl -w use strict; use Data::Dumper; my %vxdg; my $var; my ($node,$disk) = (3, "C:"); print "node= $node disk=$disk\n"; print "orignal hash is:", Dumper \%vxdg; print "\$var is: \"", (defined $var) ? $var : "undefined", "\"","\n"; $var = exists $vxdg{$node}{$disk} ? $vxdg{$node}{$disk} : ''; print "the hash is now...after checking for",'$vxdg{$node}{$disk}:', "\n", Dumper \%vxdg; print "\$var is: \"", (defined $var) ? $var : "undefined", "\"","\n"; print "\n***Starting over..***\n"; %vxdg=(); $var=undef; print "orignal hash is:", Dumper \%vxdg; $var = $vxdg{$node}{$disk} //= ''; print "the hash is now...:", "\n", Dumper \%vxdg; print "\$var is: \"", (defined $var) ? $var : "undefined", "\"","\n"; __END__ node= 3 disk=C: orignal hash is:$VAR1 = {}; $var is: "undefined" the hash is now...after checking for$vxdg{$node}{$disk}: $VAR1 = { '3' => {} }; $var is: "" ***Starting over..*** orignal hash is:$VAR1 = {}; the hash is now...: $VAR1 = { '3' => { 'C:' => '' } }; $var is: ""
Re^4: Short form (ternary) if else
by gg48gg (Sexton) on Feb 08, 2012 at 22:10 UTC
    ok I think I get it. It returns a value if true, else return value if false. It does not execute code if true or code if false. Is that a correct statement?
      Wrong, it can indeed execute code:
      sub foo1 { print "Hello, World!\n"; } sub foo2 { print "Goodbye, World!\n"; } 1 ? foo1() : foo2(); 0 ? foo1() : foo2();
      This prints:
      Hello, World! Goodbye, World!
      I think what you're confused about is still scope; like the if/else block in the original post, if you declare my $vxdg inside the ternary operator, it will fall out of scope before you try to access it again.