Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Short and easy way to write if...elsif syntax

by slayedbylucifer (Scribe)
on Aug 27, 2012 at 09:26 UTC ( #989949=perlquestion: print w/ replies, xml ) Need Help??
slayedbylucifer has asked for the wisdom of the Perl Monks concerning the following question:

hello Monks.

Is there a qquick and dirty way to write multiple if...elsif statement.

e.g. below block of code works fine for me, but it looks too amateurish.

foreach (@array) { if ( $_ =~ m/linux/ ) { print "This is linux VM" . "\n"; } elsif ( $_ =~ m/Windows/ ) { print "This is a Windows VM" ."\n"; } elsif ( $_ =~ m/Other/ ) { print "I have no idea what it is". "\n"; } }

Thanks for your time.

Comment on Short and easy way to write if...elsif syntax
Download Code
Re: Short and easy way to write if...elsif syntax
by moritz (Cardinal) on Aug 27, 2012 at 09:30 UTC
      I wasn't aware of the "say" function. thanks for the suggestion and also thanks for the perl6 link that you have provided at the bottom of your response..
Re: Short and easy way to write if...elsif syntax
by grizzley (Chaplain) on Aug 27, 2012 at 09:55 UTC
    Somehow funny way:
    %versions= ( 'linux' => sub { print "This is linux VM\n" }, 'Windows' => sub { print "This is a Windows VM\n" } ); # create this list once before loop my $idlist = join "|", keys %versions; @array = ('linux', 'Windows', 'OSX'); foreach(@array) { if(/$idlist/) { my $id = $&; &{$versions{$id}}(); } else { print "I have no idea what it is\n"; } }

    Update: please be careful with this approach, as you will have problems if one sysname is included in another one, e.g. 'Windows' and 'Windows 7' (well, actually this is a problem in your original if / elsif list, too.)

Re: Short and easy way to write if...elsif syntax
by GrandFather (Cardinal) on Aug 27, 2012 at 11:14 UTC

    Depending on your real application, it may be that a dispatch table would serve you well. Consider:

    use strict; use warnings; my %oss = (linux => \&isLinux, Windows => \&isWindows, undef => \&isOt +her); my @array = qw(linux Windows wibble); exists $oss{$_} ? $oss{$_}->() : $oss{undef}->() for @array; sub isLinux { print "This is linux VM" . "\n"; } sub isWindows { print "This is a Windows VM" . "\n"; } sub isOther { print "I have no idea what it is" . "\n"; }

    Prints:

    This is linux VM This is a Windows VM I have no idea what it is
    True laziness is hard work
Re: Short and easy way to write if...elsif syntax
by sundialsvc4 (Abbot) on Aug 27, 2012 at 11:14 UTC

    Does it work?   Is it crystal clear?   Is it maintainable?

    If the next condition that needs to be tested, for the next version of the software or for the next wild-hare idea that comes in from Marketing, is slightly different, will the logic still answer all of the preceding questions in the affirmative?   (Hint:   “No.”)

      To the “down-voters” among you, who may mistake brevity for lack of wisdom or experience, I invite your reconsideration.   Here’s why.

      The “clever improvements” as suggested cause each of the various if cases to become coupled.   In other words, as long as each and every if-case that could possibly be required, for the entire service lifetime of this application (which could be a decade or more), is identical ... the code is “clever,” and perhaps it may look a wee bit more agreeable to the digestion.

      However ...

      Change will come.   Some day, a condition will need to be added that will break the rule.   And, when that happens, suddenly the code that is working properly now must be torn-apart, more or less, and recoded.   What was meant to be clever has just turned bad, and it de-stabilized all of the logic that it “cleverly” tied together.   Whereas, if the “ugly” if..elsif structure had simply been retained, no changes to any of the existing code, with its admittedly repetitive structure, would have been required.   You would simply need to add another elsif block at the appropriate point.   You can keep that up indefinitely.

      Please bear in mind that I have spent most of my career in “code rescue” and project-turnarounds.   Which means that my perspective on such things is somewhat like that of a coroner.   Such “cleverness,” well-intentioned though it once may have been, after a surprisingly short amount of time attracts a large number of blowflies.   Maintainability is king, and software must be designed in anticipation of a very long service life involving many different people.   You won’t be at that job forever ... but your work will be, and someday I might be called in to have a look.

        The “clever improvements” as suggested cause each of the various if cases to become coupled.

        (Some annoying typography elided.) How so—especially in the given/when case?

        The real problem here could be probably the choice of a hash for this work. The idea behind a hash should be that keynames are unique and not subject to small variations, like in this case.

Re: Short and easy way to write if...elsif syntax
by Athanasius (Monsignor) on Aug 27, 2012 at 11:57 UTC

    For the problem as given, the following simple approach may be useful:

    #! perl use strict; use warnings; my @array = ('Mastering linux is a steep learning curve', 'Using Windows can be frustrating', 'Plan 9 is rarely seen'); print /linux/ ? "This is linux VM\n" : /Windows/ ? "This is a Windows VM\n" : "I have no idea what it is\n" for @array;

    Output:

    This is linux VM This is a Windows VM I have no idea what it is

    See Conditional Operator. But note that this approach is not generally scalable for dealing with more complex conditions. And see the thread if statement confusion for the syntactic pitfalls.

    Hope that helps,

    Athanasius <°(((><contra mundum

Re: Short and easy way to write if...elsif syntax
by BillKSmith (Chaplain) on Aug 27, 2012 at 12:14 UTC

    There sure is more than one way to do it!

    use strict; use warnings; $_ = 'foofum'; do{ my $print_buffer = /linux/ ? 'This is a linux VM' : /Windows/ ? 'This is a Windows VM' : 'I have no idea what it is' ; print $print_buffer, "\n"; };
    Bill
Re: Short and easy way to write if...elsif syntax
by pvaldes (Chaplain) on Aug 27, 2012 at 13:37 UTC
    my @array = ("linux", "milinus","Windows","windows","Linux"); foreach (@array){ if (/((linux|Windows))/i){ print "This is $1 VM" . "\n" } else { print "no idea" . "\n" } }

    ... mmmh, or even:

    foreach (@array){/((linux|Windows))/i ? print "This is $1 VM\n": print "no idea\n"}

    (in fact you don't need an array for this)

    print "THIS is $^O\n";

    Therefore you could still eliminate two or three characters:

    foreach (@array){/(($^O|Windows))/i ? print "This is $1 VM\n": print "no idea\n"}
      thank you very much everyone for your time. I will be learning quite a few Perl feature which were discussed in this thread. thanks again.
Re: Short and easy way to write if...elsif syntax
by davido (Archbishop) on Aug 27, 2012 at 19:27 UTC

    This is one of Perl's classical answers to the "switch" statement. In fact, if someone had simply created another name for "foreach" called "switch", we might have been spared the confusion that given has brought upon us.

    foreach ( @array ) { /linux/ && do { print "This is a linux VM.\n"; next; }; /Windows/ && do { print "This is a Windows VM.\n"; next; }; /Other/ && do { print "I have no idea what it is.\n"; next; }; die "You shouldn't be seeing this: No pattern matched.\n"; }

    Dave

Re: Short and easy way to write if...elsif syntax
by LanX (Canon) on Aug 28, 2012 at 08:58 UTC
    no need to repeat $_ =~ and just add next to avoid fall thru.

    for ($given){ print "\nFOR($_):"; if (/abc/) { print "abc"} if (/def/) { print "def" ;next} if (/xyz/) { print "xyz" ;next} print "default"; }

    more examples at Understanding the benefit of Given/When ...

    Cheers Rolf

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://989949]
Approved by moritz
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (16)
As of 2014-10-01 20:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    What is your favourite meta-syntactic variable name?














    Results (38 votes), past polls