Pathologically Eclectic Rubbish Lister PerlMonks

### Perl 5.10: switch statement demo

by talexb (Canon)
 on Dec 19, 2007 at 20:07 UTC Need Help??
talexb has asked for the wisdom of the Perl Monks concerning the following question:

Growing up with an actuary as a Father meant lots of mathematics while growing up. OK, I had an aptitude for it, that helped. There were a lot of number and word games, and one of them was called fizz-buzz. You could play it anywhere, around the dinner table, while out for a walk in the Morgan Arboretum, or on a long car ride to or from Cape Cod. It goes like this:

The players recite the numbers in ascending order, starting at 1, except when you get to a multiple of 3, you say 'fizz', and when you get to a multiple of 5 you say 'buzz'. The number before 16, is, of course, fizz-buzz. To make things more interesting and a bit more challenging, my Father added 'sausage' when the number was a multiple of 7, thus the trifecta was fizz-buzz-sausage after 104 turns.

This morning I wanted to try out Perl's new switch statement ..

```#!/usr/bin/perl510

use feature 'switch';
use feature 'say';

{
for ( 1..40 ) {
my @what;
given ( \$_ ) {

when ( \$_ % 3 == 0 ) { push ( @what, 'fizz' ); }
when ( \$_ % 5 == 0 ) { push ( @what, 'buzz' ); }
when ( \$_ % 7 == 0 ) { push ( @what, 'sausage' ); }
}
say join(' ',\$_,@what);
}
}

but found it didn't produce the output I expected. Unlike C's switch statement, once a condition is met, the entire given construct is finished.

```1
2
3 fizz
4
5 buzz
6 fizz
7 sasusage
8
9 fizz
10 buzz
11
12 fizz
13
14 sasusage
15 fizz
16
17
18 fizz
19
20 buzz
21 fizz
22
23
24 fizz
25 buzz
26
27 fizz
28 sasusage
29
30 fizz
31
32
33 fizz
34
35 buzz
36 fizz
37
38
39 fizz
40 buzz

That's OK -- now I know. Oh, and to get this to run, I had to run Perl 5.10 from the directory I built it in, and include -Ilib on the command line (thanks mauke). I made the mistake of upgrading the system Perl one time, and that's a mistake I won't ever make again.

Alex / talexb / Toronto

"Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

Replies are listed 'Best First'.
Re: Perl 5.10: switch statement demo
by Limbic~Region (Chancellor) on Dec 19, 2007 at 20:24 UTC
talexb,
Golf Challenge: FizzBuzz may be of interest to you. Also, take a look at perlsyn. While there is an implicit break in every when clause, you can get around this by using an explicit continue. A few other notes, you could use feature qw/say switch/;. There is more discussion of perl 5.10 doodads at Bring Out Your New Perl Code. For example:
```#!/usr/bin/perl
use 5.010;
use strict;
use warnings;

for (1 .. 105) {
my \$what = '';
given (\$_) {
when (not \$_ % 3) { \$what .= ' fizz'; continue }
when (not \$_ % 5) { \$what .= ' buzz'; continue }
when (not \$_ % 7) { \$what .= ' sausage' }
}
say "\$_\$what";
}

Cheers - L~R

I wonder why you switched from "when the remainder is zero" to "when not the remainder". (Reminds me of the baby in Dinosaurs: "Not the Momma! Not the Momma!")

Update: Nevermind, I guess it can be read "when no remainder". I guess I don't think of a remainder of zero as there being no remainder, so it looks weird to me.

The modulo construct can also be thought of as 'divisible by' -- so \$foo % 3 checks to see if \$foo is divisible by 3. Or at least that's the way my brain works.

Alex / talexb / Toronto

"Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

Re: Perl 5.10: switch statement demo
by jdporter (Canon) on Dec 19, 2007 at 20:26 UTC

That doesn't look like a particularly apt illustration of given/when anyway, since it completely circumvents given's smart matching. It certainly doesn't look any better than

```        \$_ % 3 or push @what, 'fizz';
\$_ % 5 or push @what, 'buzz';
\$_ % 7 or push @what, 'sausage';

which, as you pointed out, DWYM in this case, while given/when doesn't.

A word spoken in Mind will reach its own level, in the objective world, by its own weight
Re: Perl 5.10: switch statement demo
by Thilosophy (Curate) on Dec 20, 2007 at 01:34 UTC
but found it didn't produce the output I expected. Unlike C's switch statement, once a condition is met, the entire given construct is finished.

It has been pointed out that you can explicitly continue to produce the output you expected.

Please note, however, that the behaviour of continue is very much different from the fall-through in C, in that the next when condition is still being checked; in C, you go to the contents of the next case without any checks (which would not make much sense in a switch/case anyway).

So the C behaviour (which is difficult to reproduce with the Perl given construct,see this thread) would not produce your expected output either.

Re: Perl 5.10: switch statement demo
by ikegami (Pope) on Dec 19, 2007 at 22:48 UTC
Judging by how often people forget to place break;, it's much more natural for us to think of cases as exclusive. Or maybe it's because it's much more common to want exclusive cases, in which case it also saves us needless typing.
Judging by how often people forget to place break;, it's much more natural for us to think of cases as exclusive.

I dunno -- remembering to add the break; is just one of the things that I know and will never forget when I write C. You can call it a feature or a bug, but it's part of the language that I know.

I didn't write the node to complain, really, it's more of a warning for anyone else who grew up writing C. And it's spawned a couple of really good responses detailing alternative approaches that work, both before and after 5.10. And that discussion, by itself, is very useful.

Alex / talexb / Toronto

"Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

Re: Perl 5.10: switch statement demo
by LighthouseJ (Sexton) on Dec 20, 2007 at 13:42 UTC
I don't know why people want a verbatim 'switch' statement when you can use a for-statement.
```#!/usr/bin/perl -w
use strict;
{
for (1..40) {
print;
(\$_ % 3 == 0) && print q! fizz!;
(\$_ % 5 == 0) && print q! buzz!;
(\$_ % 7 == 0) && print q! sausage!;
print "\n";
}
}

I generally use a for loop in conjunction with regular expression matches, like this trivial example:
```#!/usr/bin/perl -w
use strict;
{
my @items = qw/The three principal virtues of a programmer are Laz
+iness, Impatience, and Hubris. See the Camel Book for why/;
for (@items) {
/^[A-Z]/ && do {
print "Found a proper noun?  \$_\n";
next;
};

/[,.]/ && do {
print "This word has punctuation:  \$_\n";
next;
};

print "This word seems uninteresting:  \$_\n";
}
}

It has a lot of flexibility where you can mix and match parts and get real nice uses out of it. I've always used it fully and got very good results --without waiting for a proper switch statement.

"The three principal virtues of a programmer are Laziness, Impatience, and Hubris. See the Camel Book for why." -- `man perl`
You can use when in a for loop:
```for (@items) {
when (/^[A-Z]/) {
say "Found a proper noun?  \$_";
}

when (/[,.]/) {
say "This word has punctuation:  \$_";
}

say "This word seems uninteresting:  \$_";
}
I guess that's kind of my point. The really useful and powerful things in todays computing industry like Perl, UNIX, even RISC processors all merely provide you with a basic set of tools and rely on you (the user) to put the simple tools together to make a useful mechanism.

Stuff like adding a named "switch" statement or needing a "when" keyword just complicates it unnecessarily IMO.

"The three principal virtues of a programmer are Laziness, Impatience, and Hubris. See the Camel Book for why." -- `man perl`

Create A New User
Node Status?
node history
Node Type: perlquestion [id://657959]
Approved by marto
Front-paged by Corion
help
Chatterbox?
 [shmem]: straight list or named parameters - that depends on whether (and how many) optional arguments you have [Discipulus]: if so a plain list is ok, imho [Lady_Aleena]: shmem, I already have the plugin installed, just not active. [shmem]: if you have 1 optional argument, place that at the end of the list. If you have more, go for named parameters. [Lady_Aleena]: 1 manditory, 2 optional. [Discipulus]: my (\$need,\$opta,\$optb ) = @_; .. if \$opta.. [shmem]: all else leads to trouble, even if the third argument depends on the existence of the second. That may become brittle. [Discipulus]: but if have case like subname(15,undef,3 ) maybe bettere named parameters [Lady_Aleena]: I don't want to have to do: alpha_menu(\$hash, undef, \$type); [Lady_Aleena]: Or what Discipulus said.

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (8)
As of 2017-04-27 12:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
I'm a fool:

Results (506 votes). Check out past polls.