Skip to content

given/when – the Perl switch statement

August 30, 2010

Its been a while since my last post; summer holidays have inflicted upon me some big distractions! So to ease myself back in gently I’ll I’ve pulled out a (nearly finished but unposted) article from last year (in true Blue Peter tradition!)

This post was inspired by this nice & straightforward blog article: How A Ruby Case Statement Works And What You Can Do With It. I’ve simply converted the Ruby code to Perl and added some so called insightful notes 🙂

Now what Ruby calls case/when statements is more commonly known in computer parlance has the switch statement.

Perl itself has had such a switch statement for quite a while now:

use Switch;

switch ($grade) {
    case "A"   { say "Well done!" }
    case "B"   { say "Try harder!" }
    case "C"   { say "You need help!!!" }
    else         { print "You just making it up" }
}

However DON’T USE IT!!! Its a source filter and is being deprecated.

Instead use given/when which is the Perl 6 switch statement that was introduced at perl 5.10.

use strict;
use warnings;
use feature qw(switch say);

print 'Enter your grade: ';
chomp( my $grade = <> );

given ($grade) {
    when ('A') { say 'Well done!'       }
    when ('B') { say 'Try harder!'      }
    when ('C') { say 'You need help!!!' }
    default { say 'You are just making it up!' }
}

And at perl 5.12 you could also use when has a statement modifiers:

use 5.012;
use warnings;

print 'Enter your grade: ';
chomp( my $grade = <> );

given ($grade) {
    say 'Well done!'        when 'A';
    say 'Try harder!'       when 'B';
    say 'You need help!!!'  when 'C';
    default { say 'You are just making it up!' }
}

And even more enhancements are coming with perl 5.14 because given now returns the last evaluated expression:

use 5.013;  # 5.014
use warnings;

print 'Enter your grade: ';
chomp( my $grade = <> );

say do { 
    given ($grade) {
        'Well done!'        when 'A';
        'Try harder!'       when 'B';
        'You need help!!!'  when 'C';
        default { 'You are just making it up!' }
    }
};

Which can lead to some very pleasant looking dry code.

But there is more to given/when than just single value conditionals. You can also check multi-values and ranges:

use 5.012;
use warnings;

print 'Enter your grade: ';
chomp( my $grade = <> );

given ($grade) {
    say 'You pretty smart'  when ['A', 'B'];
    say 'You pretty dumb!!' when ['C', 'D'];
    default { say "You can't even use a computer" }
}

And also pattern match using a regex:

use 5.012;
use warnings;

print 'Enter some text: ';
chomp( my $some_string = <> );

given ($some_string) {
    say 'String has numbers'  when /\d/;
    say 'String has letters'  when /[a-zA-Z]/;
    default { say "String has no numbers or letters" }
}

In fact you can use anything that Smart Matching can resolve.

And because smart matching is used under the hood by given/when then you can customise it by overloading the ~~ smart match operator:

use 5.012;
use warnings;

{
    package Vehicle;
    use Moose;
    use overload '~~' => '_same_wheels', fallback => 1;
    
    has number_of_wheels => (is => 'rw', isa => 'Int');
    
    sub _same_wheels {
        my ($self, $another_vehicle) = @_;
        $self->number_of_wheels == $another_vehicle->number_of_wheels;
    } 
}

my $four_wheeler =  Vehicle->new( number_of_wheels =>  4 );
my $two_wheeler  =  Vehicle->new( number_of_wheels =>  2 );
my $robin_reliant = Vehicle->new( number_of_wheels =>  3 );

print 'Enter number of wheel for vehicles: '; chomp( my $wheels = <> );
my $vehicle = Vehicle->new( number_of_wheels => $wheels );

given ($vehicle) {
    say 'Vehicle has the same number of wheels as a two-wheeler!'
        when $two_wheeler;
    
    say 'Vehicle has the same number of wheels as a four-wheeler!'
        when $four_wheeler;
        
    say 'Gosh... is that Del Trotter!!'
        when $robin_reliant;
      
    default { 
        say   "Don't know of a vehicle with that wheel arrangement!"
    }
}

Hopefully that was a nice lightweight introduction to given/when. And I haven’t even touched upon break or continue 🙂

/I3az/

12 Comments leave one →
  1. Naveed permalink
    September 1, 2010 3:23 am

    This was a really good overview of given/when. I wanted to subscribe to your rss feed, but the rss link on the right side is broken. At least for my browser, google chrome.

  2. October 8, 2010 12:09 pm

    This post got linked to on #perl6 IRC channel: http://irclog.perlgeek.de/perl6/2010-09-30

  3. February 6, 2011 11:17 am

    NB. This article was “Hacker News”-ed (!) a couple of weeks ago: http://news.ycombinator.com/item?id=2132517

  4. November 21, 2011 5:31 am

    Thanks for the examples. I was about to use a switch

  5. Fahad permalink
    February 3, 2012 4:03 pm

    pretty cool,Both given/when and your post.

  6. R. Eitz permalink
    April 14, 2014 6:06 pm

    Very good examples on given. Thank you.

  7. Phil permalink
    March 27, 2015 8:49 pm

    Why do the people who decide on Perl syntax so often choose to take existing, well-known constructs and give them different names JUST TO CONFUSE EVERYBODY? It seems deliberately evil.

    • May 29, 2015 12:52 pm

      If its an improvement then I’m all for it. And I would definitely say given/when is a great improvement over switch/case (and variants).

Trackbacks

  1. Given/when – The Perl switch statement « Interesting Tech
  2. given/when – the Perl switch statement « transfixed but not dead! « The S.T.U.P.I.D. Crespo
  3. Delicious Bookmarks for June 15th through June 16th « Lâmôlabs

Leave a reply to R. Eitz Cancel reply