Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Ternary Operator with Subroutine

by Anonymous Monk
on Aug 11, 2011 at 18:44 UTC ( [id://919930]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

When I run this code, it complains that

"Useless use of reference constructor in void context."

Can someone tell me what is going on?
#!/usr/bin/perl use strict; use warnings; ( my $test ) ? print 'c' : sub { print 'a'; print 'b' }
On the other hand, this works.
#!/usr/bin/perl use strict; use warnings; ( my $test ) ? print 'c' : print_me(); sub print_me { print 'a'; print 'b'; }

Replies are listed 'Best First'.
Re: Ternary Operator with Subroutine
by BrowserUk (Patriarch) on Aug 11, 2011 at 19:03 UTC

    This would work:

    ( my $test ) ? print 'c' : sub { print 'a'; print 'b' }->();

    But this is probably what you want:

    ( my $test ) ? print 'c' : do{ print 'a'; print 'b' };

    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.

      There must be something I didnt understand yet, so I excuse my question, dear Monks. But why would anyone would like to do that? Is there any possibility, that

      my $test
      may fail?

      It seems to me like writing

      if (1) { print "some"; } else { print "thing"; }
      (And in that case, I could imagine some kind of debug-switch or so).

      Please enlighten me.

        Is there any possibility, that my $test may fail?

        Actually, it will always "fail". That is, an uninitialised variable is always undef, and therefore false.

        It also doesn't make much sense to do print 'a'; print 'b'; instead of print 'a', 'b'; or print 'ab';.

        I think it is fair to assume that the code supplied it greatly simplified example and that ( my $test ) is just a placeholder for 'some boolean condition' rather than an actual variable declaration.


        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.

      The statement…

      ( my $test ) ? print 'c' : do{ print 'a'; print 'b' };

      …is much better written…

      print 'a'; print 'b';

        No shit Sherlock!


        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.
Re: Ternary Operator with Subroutine
by AR (Friar) on Aug 11, 2011 at 18:59 UTC

    The difference between the two is that in the first example, you are creating an anonymous subroutine and not saving a reference to it so you'll never be able to access it. The second example is running a named subroutine, which is perfectly legitimate.

Re: Ternary Operator with Subroutine
by pemungkah (Priest) on Aug 12, 2011 at 07:47 UTC
    Specifically:
    sub { print 'a'; print 'b' }
    constructs a code reference; if you saved this, you could call it later. It does not execute the code! That's the "reference constructor" in the message.

    You're not assigning the result of this constructor to anything, which is the "void context" part.

    So Perl is saying "you made an anonymous sub reference and then you threw it away. Did you actually want to do that?"

Re: Ternary Operator with Subroutine
by biohisham (Priest) on Aug 11, 2011 at 23:08 UTC
    When you assign to a reference a value (in this case an anonymous sub), dereference that reference to access its value:
    hisham@bioslayer:~$ perl - my $subref = sub{print 'a',"\n";}; (my $test)?print 'c' : $subref->(); #dereference with infix arrow oper +ator __END__ a hisham@bioslayer:~$ perl - my $subref = sub{print 'a',"\n"}; (my $test)?print 'c' : &{$subref}; #dereference with &{} __END__ a
    check %perldoc perlsub


    David R. Gergen said "We know that second terms have historically been marred by hubris and by scandal." and I am a two y.o. monk today :D, June,12th, 2011...
Re: Ternary Operator with Subroutine
by Jim (Curate) on Aug 14, 2011 at 15:54 UTC

    First, Perl's conditional operator is a ternary operator, but it's called "conditional operator," not "ternary operator." The "conditional operator" is a specific operator; "ternary operator" describes a kind of operator.

    Use the conditional operator only for conditional statements that return a single result—one scalar, list, hash, reference, etc.—and use it only for what it returns. In general, use it mostly for assigments to variables. Don't put program behavior—actions—inside the return-this parts of conditional operators. For that, use if-then-else statements instead. Your code will be more readable, more understandable, and more maintainable.

    So…

    my $test_result = <some test that returns a Boolean value>; print $test_result ? qw( c ) : qw( a b );

    …or, better…

    my $test_result = <some test that returns a Boolean value>; my @values = $test_result ? qw( c ) : qw( a b ); print @values;

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (7)
As of 2024-04-23 08:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found