Beefy Boxes and Bandwidth Generously Provided by pair Networks chromatic writing perl on a camel
No such thing as a small change
 
PerlMonks  

Warning while using ternary operator

by simonz (Acolyte)
on Dec 16, 2013 at 10:49 UTC ( #1067306=perlquestion: print w/ replies, xml ) Need Help??
simonz has asked for the wisdom of the Perl Monks concerning the following question:

Hi,
I am getting a warning while executing the following code in case where I am not using any variable for the ternary operator. Why I am getting warning like "Useless use of a constant in void context at a.pl" for not using the variable ? How can I write the code without using the variable and not getting the warning as well.

my $hash = {}; my $i = "one"; #Below line giving no warning. But I DO NOT want this #my $val = ($i eq 'one') ? $hash->{'name'} = "hello"."world" : 'nothin +g'; # Below line giving warning. But I want this ($i eq 'one') ? $hash->{'name'} = "hello"."world" : 'nothing';

Comment on Warning while using ternary operator
Download Code
Re: Warning while using ternary operator
by BrowserUk (Pope) on Dec 16, 2013 at 10:53 UTC

    When $i ne 'one', the constant:  'nothing' is not assigned to anything, thus in a void context.

    Did you want:

    $hash->{'name'} = ($i eq 'one') ? "hello"."world" : 'nothing';

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Yes , you are right, I want what you just mentioned.
      But my question is where does $i ne 'one' is happening in my code ? $i is assgined to 'one' and not getting changed.

        But my question is where does $i ne 'one' is happening in my code ? $i is assgined to 'one' and not getting changed.

        The point is that the compiler knows at compile-time that 'nothing' is in a void context; so it warns you.

        You can choose to ignore that warning; or you could even disable it; but it is surely better to simply correct the code.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        where does $i ne 'one' is happening in my code ?

        It isn’t! To see this, print out the values of $hash->{name} and $i:

        #! perl use strict; use warnings; my $hash = {}; my $i = 'one'; print "\nOriginal code:\n\n"; ($i eq 'one') ? $hash->{'name'} = "hello"."world" : 'nothing'; printf "name: %s, i: %s\n", $hash->{name}, $i; print "\nBrowserUk's fix:\n\n"; $hash->{name} = ($i eq 'one') ? "hello" . "world" : 'nothing'; printf "name: %s, i: %s\n", $hash->{name}, $i;

        Output:

        22:46 >perl 801_SoPW.pl Useless use of a constant ("nothing") in void context at 801_SoPW.pl l +ine 21. Original code: name: helloworld, i: one BrowserUk's fix: name: helloworld, i: one 22:46 >

        As you can see, the warning is printed before the script runs, because it’s a compile-time warning, as BrowserUk says. But in both cases, the result of the assignment is that $hash->{name} contains helloworld, showing that $i eq 'one' is true. What makes you think that $i becomes not equal to 'one'?

        For the ternary operator, see perlop#Conditional-Operator.

        Hope that helps,

        Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

        It sounds almost like you expect c<$i> to be updated - which won't happen; Are you are confusing a test with an assignment - the eq operator tests for string equality between the LHS and RHS, it is most definitely not an assignment operator.

        A user level that continues to overstate my experience :-))
Re: Warning while using ternary operator
by Anonymous Monk on Dec 16, 2013 at 13:42 UTC
    The ternary operator is not a shorthand way of writing an if block. It's a shorthand way of writing an if block that returns a value.
    if ($expression) { $var = "foo"; } else { $var = "bar"; } # WRONG $expression ? $var = "foo" : $var = "bar"; # correct $var = $expression ? "foo" : "bar";

      This is bad information.

      The expression

      $expression ? $var = "foo" : $var = "bar";

      is only "# WRONG" because of operator precedence (see perlop: Operator Precedence and Associativity). Here's how it is parsed:

      $ perl -MO=Deparse,-p -e '$expression ? $var = "foo" : $var = "bar";' (($expression ? ($var = 'foo') : $var) = 'bar'); -e syntax OK

      This is explained in perlop: Conditional Operator. Correcting the precedence with parentheses:

      $ perl -MO=Deparse,-p -e '$expression ? ($var = "foo") : ($var = "bar" +);' ($expression ? ($var = 'foo') : ($var = 'bar')); -e syntax OK

      I do not dispute that '$var = $expression ? "foo" : "bar";' is a better way to write '$expression ? ($var = "foo") : ($var = "bar");'. In fact, the documentation also recommends this.

      Once corrected as indicated, here's how your "# WRONG" code behaves:

      #!/usr/bin/env perl -l use strict; use warnings; for my $expression (0, 1) { my $var = ''; $expression ? ($var = 'foo') : ($var = 'bar'); print "\$expression = '$expression'; \$var = '$var'"; }

      Output:

      $expression = '0'; $var = 'bar' $expression = '1'; $var = 'foo'

      -- Ken

        But what does the syntactically correct statement
            $expression ? $var = "foo" : $var = "bar";
        actually do?

        >perl -wMstrict -le "for my $expression (0, 1) { my $var = ''; $expression ? $var = 'foo' : $var = 'bar'; print qq{if \$expression is $expression, \$var is '$var'} } " if $expression is 0, $var is 'bar' if $expression is 1, $var is 'bar'

        It seems the statement is just an expensive equivalent to the statement
            $var = 'bar';
        The reason why is left as a exercise for simonz (after the recommended perusal of perlop :)

Re: Warning while using ternary operator
by mward (Initiate) on Dec 17, 2013 at 11:46 UTC

    If what you really want is:

    • Assign "hello"."world" to the hash when ($i eq 'one')
    • Do nothing when ($i ne 'one')

    Then one way to achieve this is:

    ($i eq 'one') ? $hash->{'name'} = "hello"."world" : 0;

    Executing "0" does not give a warning, unlike executing 'nothing'.

      Though that would be a hell of a lot more readable as:

      $hash->{'name'} = "hello"."world" if $i eq 'one';
      use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1067306]
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (15)
As of 2014-04-17 13:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (448 votes), past polls