Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

true/false condition - what am I doing wrong?

by ultranerds (Hermit)
on Dec 08, 2011 at 14:10 UTC ( [id://942439]=perlquestion: print w/replies, xml ) Need Help??

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

Hi,

I'm trying to do a basic function that with set $redo bases on the value of $type (either "add" or "edit) ... this is the sample code:

my $type = "add"; my $redo; $type eq "add" ? $redo = "wiki_add2" : $redo = "wiki_edit2"; print "With type: $type, we could redo: $redo \n"; my $type = "edit"; my $redo; $type eq "add" ? $redo = "wiki_add2" : $redo = "wiki_edit2"; print "With type: $type, we could redo: $redo \n";


For some reason it always returns "wiki_edit2" ... what am I doing wrong?

TIA!

Andy

Replies are listed 'Best First'.
Re: true/false condition - what am I doing wrong?
by Taulmarill (Deacon) on Dec 08, 2011 at 14:23 UTC
    The correct way to use the teary operator would be like this:
    $redo = $type eq "add" ? "wiki_add2" : "wiki_edit2";
    I would like to tell you what exactly happens, when perl executes your version. But to be honest i can't quite figure it out.

      Exactly! Taulmarill has pointed it out right. You are using a compound if statement without the appropriate syntax. Also, I notice in your code that you've declared the variables $type and $redo twice within the same lexical scope! You might like to change this.

      Thanks guys - duh I should have seen that one. Joys of trying to work when you have a stinking headache and cold

      Thanks!

      Andy
Re: true/false condition - what am I doing wrong?
by Anonymous Monk on Dec 08, 2011 at 14:58 UTC

    B::Deparse!!!

    $ perl -MO=Deparse,-p junk (my $type = 'add'); my($redo); ((($type eq 'add') ? ($redo = 'wiki_add2') : $redo) = 'wiki_edit2'); print("With type: $type, we could redo: $redo \n"); junk syntax OK $ perl -MO=Deparse,-p junk | perltidy junk syntax OK ( my $type = 'add' ); my ($redo); ( ( ( $type eq 'add' ) ? ( $redo = 'wiki_add2' ) : $redo ) = 'wiki_edi +t2' ); print("With type: $type, we could redo: $redo \n");
Re: true/false condition - what am I doing wrong?
by tobyink (Canon) on Dec 08, 2011 at 19:23 UTC

    I've always quite liked this idiom, which scales nicely when you've got lots of choices:

    my $type = "add"; my $redo = { add => "wiki_add2", edit => "wiki_edit2", delete => "wiki_remove3", }->{$type} || "wiki_noneoftheabove7"; print "With type: $type, we could redo: $redo \n";

    Also since Perl 5.10, we've had the given keyword. Unless you're targeting legacy releases of Perl, that's probably your best bet:

    my $type = "add"; my $redo; given ($type) { when ("add") { $redo = "wiki_add2" } when ("edit") { $redo = "wiki_edit2" } when ("remove") { log("REMOVE") and $redo = "wiki_remove2" } default { $redo = "wiki_noneoftheabove7" } } print "With type: $type, we could redo: $redo \n";

    In Perl 5.12 onwards, when can be used as a (postfix) statement modifier:

    my $type = "add"; my $redo; given ($type) { $redo = "wiki_add2" when "add"; $redo = "wiki_edit2" when "edit"; when ("remove") { log("REMOVE") and $redo = "wiki_remove2" } default { $redo = "wiki_noneoftheabove7" } } print "With type: $type, we could redo: $redo \n";

    And from Perl 5.14, it gets even better, as given has a useful return value.

    my $type = "add"; my $redo = given ($type) { "wiki_add2" when "add"; "wiki_edit2" when "edit"; when ("remove") { log("REMOVE") and "wiki_remove2" } default { "wiki_noneoftheabove7" } }; print "With type: $type, we could redo: $redo \n";
Re: true/false condition - what am I doing wrong?
by Anonymous Monk on Dec 08, 2011 at 14:28 UTC

    I believe that's the equivalent of $type eq "add" ? ($redo = "wiki_add2" : $redo) = "wiki_edit2"; where the chained ='s apply the last value to everything.

    In general, adding brackets to the false part will fix you right up.

    $type eq "add" ? $redo = "wiki_add2" : ($redo = "wiki_edit2");

    In this specific case, you want what Taulmarill posted to avoid repeating yourself on the "$redo =" part.

Re: true/false condition - what am I doing wrong?
by Marshall (Canon) on Dec 08, 2011 at 15:30 UTC
    This is an abuse of the ternary operator.

    Normally in this situation, you want to choose between 3 choices, not two!

    Use the ternary operator to set a variable dependent upon a true/ false condition.
    A common use would be like this:
    ($today eq 'Monday') ? $firstDay =1 : $firstDay =0;

    That would be preferred over:
    $firstDay=0;
    $firstDay=1 if ($today eq 'Monday');

    Use if and if/elsif/else conditions for more complicated things.

    #!/usr/bin/perl -w use strict; decide ('add'); decide ('edit'); decide ('bad input nothing'); print "\n"; decide2 ('add'); decide2 ('edit'); decide2 ('bad input nothing'); sub decide { my $input = shift; print "invalid input\n" if ($input ne "add" and $input ne "edit"); print "doing an add\n" if $input eq "add"; print "doing an edit\n" if $input eq "edit"; } sub decide2 { my $input = shift; if ($input eq 'add') { print "the add code goes here\n"; } elsif ($input eq 'edit') { print "the edit code goes here\n"; } else { print "the invalid input code goes here\n"; } } __END__ doing an add doing an edit invalid input the add code goes here the edit code goes here the invalid input code goes here
      A common use would be like this:
      ($today eq 'Monday') ? $firstDay =1 : $firstDay =0;
      I have always thought the common use is
      $firstDay = $today eq 'Monday' ? 1 : 0;
        correct - tired this morning.. been pulling late nights on a db project...
        main point is that this is not the right place for 'edit' vs 'add'.

        Update: even more uses are possible:

        #!/usr/bin/perl -w use strict; sub is_name_valid { return $_[0]; #just a dummy } print "the name ",is_name_valid(0) ? "was" :"was not"," valid\n"; # the name was not valid print "the name ",is_name_valid(1) ? "was" :"was not"," valid\n"; # the name was valid

      The ternary operator is stackable. So for three choices, the following might be bearable:

      use strict; use warnings; for my $type ( qw(add edit nada) ) { my $redo = $type eq 'add' ? 'wiki_add2' : $type eq 'edit' ? 'wiki_edit2' : 'error'; print "$type -> $redo\n"; } __END__ add -> wiki_add2 edit -> wiki_edit2 nada -> error

      But as AM points out, the OP's task seems to call for a dispatch table.

Re: true/false condition - what am I doing wrong?
by si_lence (Deacon) on Dec 08, 2011 at 14:30 UTC
    You can use a block construct to get this to work:
    my $type = "add"; my $redo; $type eq "add" ? {$redo = "wiki_add2"} : {$redo = "wiki_edit2"}; print "With type: $type, we could redo: $redo \n";
      Did you mean 'do' block? Because using your example I get the following warnings:
      Useless use of anonymous hash ({}) in void context at test.pl line 5. Useless use of anonymous hash ({}) in void context at test.pl line 5. Odd number of elements in anonymous hash at test.pl line 5.
Re: true/false condition - what am I doing wrong?
by pvaldes (Chaplain) on Dec 08, 2011 at 14:26 UTC
    nothing

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (7)
As of 2024-03-28 12:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found