Several different solutions coming up...

use 5.010; my $x = 40; given ($x) { when ([0..9, 50..59]) { say 0 } when ([10..19, 60..69]) { say 1 } when ([20..29, 70..79]) { say 2 } when ([30..39, 80..89]) { say 3 } when ([40..49, 90..99]) { say 4 } }

As of Perl 5.14 (which is incidentally the oldest officially supported version of Perl, so if you've not upgraded yet, why not?), you can also use when as a statement modifier...

use 5.014; my $x = 40; given ($x) { say 0 when [0..9, 50..59]; say 1 when [10..19, 60..69]; say 2 when [20..29, 70..79]; say 3 when [30..39, 80..89]; say 4 when [40..49, 90..99]; }

Or smart match with no topicalising...

use 5.010; my $x = 40; say 0 if $x ~~ [0..9, 50..59]; say 1 if $x ~~ [10..19, 60..69]; say 2 if $x ~~ [20..29, 70..79]; say 3 if $x ~~ [30..39, 80..89]; say 4 if $x ~~ [40..49, 90..99];

And here's another technique using Smart::Dispatch...

use Smart::Dispatch; my $x = 40; my $tiers = dispatcher { match [0..9, 50..59], dispatch { 0 }; match [10..19, 60..69], dispatch { 1 }; match [20..29, 70..79], dispatch { 2 }; match [30..39, 80..89], dispatch { 3 }; match [40..49, 90..99], dispatch { 4 }; }; say $tiers->($x);

And a last one using a regular hash, which has the advantage that it should work with even really ancient Perl 5.x releases.

my $x = 40; my %tiers = ( (map { $_ => 0 } 0..9, 50..59), (map { $_ => 1 } 10..19, 60..69), (map { $_ => 2 } 20..29, 70..79), (map { $_ => 3 } 30..39, 80..89), (map { $_ => 4 } 40..49, 90..99), ); print $tiers{$x} . "\n";

What are the advantages of each solution? Well, a hash is nice in that it can be stored in a variable and passed around easily; it can be inspected, modified, etc. However, it can only deal with finite sets of keys. If you need to be able to match, say, all floating point numbers between 2.1 and 2.3, then you don't want to list them all in a hash!

The aim of Smart::Dispatch is to retain the benefits of hash-based dispatch tables (the ability to pass a reference to them around; inspect them; modify them) but without needing to enumerate all the hash keys.

The others, using Perl's built-in decision syntax (i.e. if, given, when, etc) will likely run a little faster (though may compile a little slower than a hash), but passing around references to them is more awkward (you'd need to write a wrapper sub and pass around references to that), and inspecting/modifying them at run-time is close to impossible. If you've got a reference to a sub wrapper for your decision tree, you can fake modifying it by installing additional wrappers around it. For example:

use 5.010; my $standard_say = sub { say 0 if $x ~~ [0..9, 50..59]; say 1 if $x ~~ [10..19, 60..69]; say 2 if $x ~~ [20..29, 70..79]; say 3 if $x ~~ [30..39, 80..89]; say 4 if $x ~~ [40..49, 90..99]; }; $standard_say->(40); # Now imagine we decide to special-case 39... my $modified_say = sub { if ($_[0] == 39) { say "yay!"; return; } $standard_say->(@_); }; $modified_say->(40); $modified_say->(39);

Doing something like that with Smart::Dispatch is a little cleaner...

use Smart::Dispatch; my $standard_say = dispatcher { match [0..9, 50..59], dispatch { say 0 }; match [10..19, 60..69], dispatch { say 1 }; match [20..29, 70..79], dispatch { say 2 }; match [30..39, 80..89], dispatch { say 3 }; match [40..49, 90..99], dispatch { say 4 }; }; $standard_say->(40); my $modified_say = dispatcher { match 39, dispatch { say "yay!" } } . +$standard_say; $modified_say->(40); $modified_say->(39);
perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

In reply to Re: Perl Number range lookup question by tobyink
in thread Perl Number range lookup question by jamesbutler

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.