Readable Perl

Preview:

DESCRIPTION

People like to claim Perl is line noise, with its sigils and regular expressions. But a lot of the features that make it possible to write, yes, truly awful, unreadable Perl, also let you write clean, maintainable code too. * those $%&* sigils! * there\'s More Than One Way To Do It * strings and data structures * map, grep, first class functions * metaprogramming and the CPAN * modern Object Oriented programming with Moose

Citation preview

/;{}def/#{def}def/$_={/Times­Boldexchselectfont}#/_{  rmoveto} #/"{dup}#/*/!/$;/q{exch}#/x ; {/J q #}#/.{/T q #}#{stringwidth}#{}#{}# 14 string dup dup dup260 40 moveto 90 rotate ; %/}};$0='"\e[7m \e[0m"';@ARGV=split//,reverseq(ThePerl). q(Journal) x 220 ; q ; 0 T putinterval exch 7 J putinterval ; ; $_= q /m$ pop T($*!$"=!$ " )pop " * true% ? $ " $!" "  !!  !! % !" !"    !! charpath {!"""}pop $ pop{""!}pop ! neg{!#}pop 220 ! neg _{!!}pop J false %Tcharpath  clip " pop 0 " moveto 6{!!}pop $_= 105{!!}pop {$ ! $ " !  #! ##}pop{dup dup $ ! " pop pop q{"}pop 22{dup show}repeat {"}pop q 22 mul{$ "} popneg{!#! $ "}pop ! 8 .65 mul{$ # # $}pop ! neg{"}pop  _ pop{"}pop } repeat pop" {  $ " ! ! ! $ " ! !" "#"  #"!"""""! #" " # "m/;@ARGV=(@ARGV[­14..­1])x50;q} 0 "%};s/m[ou]|[­\dA­ln­z.\n_{}]|\$_=//gx;s/(.)(?{$*=''})/('$*.='.(++$#%2?'':"$0;").'pop;')x(ord($1)­31).'$*'/gee;s/((.(\e\[.m)*|.){77})/$1\n/g;print; sub showpage {}@P=split//,".URRUU\c8R";@d=split//,"\nrekcah xinU / lreP rehtona tsuJ";sub p{@p{"r$p","u$p"}=(P,P);pipe"r$p","u$p";++$p;($q*=2)+=$f=!fork;map{$P=$P[$f^ord($p{$_})&6];$p{$_}=/ ^$P/ix?$P:close$_}keys%p}p;p;p;p;p;map{$p{$_}=~/^[P.]/&&close$_}%p;wait until$?;map{/^r/&&<$_>}%p;$_=$d[$q];sleep rand(2)if/\S/;print#:: ::­| ::­| .­. :||­:: 0­| .­| ::||­| .:|­. :||open(Q,$0);while(<Q>){if(/^#(.*)$/){for(split('­',$1)){$q=0;for(split){s/\|/:.:/xg;s/:/../g;$Q=$_?length:$_;$q+=$q?$Q:$Q*20;}print chr($q);}}}print"\n";#.: ::||­| .||­| :|||­| ::||­| ||­:: :|||­| .:|/;{}def/#{def}def/$_={/Times­Bold exch selectfont}#/_{rmoveto}#/"{dup}#/*/!/$;/q{exch}#/x ; {/J q #}#/.{/T q #}#{stringwidth}#{}#{}# 14 string dup dup dup

Readable Perl

GeekUp Liverpool, Tuesday 27th May, 2008http://upcoming.yahoo.com/event/691199/

hakim.cassimally@gmail.com

/;{}def/#{def}def/$_={/Times­Boldexchselectfont}#/_{  rmoveto} #/"{dup}#/*/!/$;/q{exch}#/x ; {/J q #}#/.{/T q #}#{stringwidth}#{}#{}# 14 string dup dup dup260 40 moveto 90 rotate ; %/}};$0='"\e[7m \e[0m"';@ARGV=split//,reverseq(ThePerl). q(Journal) x 220 ; q ; 0 T putinterval exch 7 J putinterval ; ; $_= q /m$ pop T($*!$"=!$ " )pop " * true% ? $ " $!" "  !!  !! % !" !"    !! charpath {!"""}pop $ pop{""!}pop ! neg{!#}pop 220 ! neg _{!!}pop J false %Tcharpath  clip " pop 0 " moveto 6{!!}pop $_= 105{!!}pop {$ ! $ " !  #! ##}pop{dup dup $ ! " pop pop q{"}pop 22{dup show}repeat {"}pop q 22 mul{$ "} popneg{!#! $ "}pop ! 8 .65 mul{$ # # $}pop ! neg{"}pop  _ pop{"}pop } repeat pop" {  $ " ! ! ! $ " ! !" "#"  #"!"""""! #" " # "m/;@ARGV=(@ARGV[­14..­1])x50;q} 0 "%};s/m[ou]|[­\dA­ln­z.\n_{}]|\$_=//gx;s/(.)(?{$*=''})/('$*.='.(++$#%2?'':"$0;").'pop;')x(ord($1)­31).'$*'/gee;s/((.(\e\[.m)*|.){77})/$1\n/g;print;                 sub showpage {}@P=split//,".URRUU\c8R";@d=split//,"\nrekcah xinU / lreP rehtona tsuJ";sub p{@p{"r$p","u$p"}=(P,P);pipe"r$p","u$p";++$p;($q*=2)+=$f=!fork;map{$P=$P[$f^ord($p{$_})&6];$p{$_}=/ ^$P/ix?$P:close$_}keys%p}p;p;p;p;p;map{$p{$_}=~/^[P.]/&&close$_}%p;wait until$?;map{/^r/&&<$_>}%p;$_=$d[$q];sleep rand(2)if/\S/;print#:: ::­| ::­| .­. :||­:: 0­| .­| ::||­| .:|­. :||open(Q,$0);while(<Q>){if(/^#(.*)$/){for(split('­',$1)){$q=0;for(split){s/\|/:.:/xg;s/:/../g;$Q=$_?length:$_;$q+=$q?$Q:$Q*20;}print chr($q);}}}print"\n";#.: ::||­| .||­| :|||­| ::||­| ||­:: :|||­| .:|/;{}def/#{def}def/$_={/Times­Bold exch selectfont}#/_{rmoveto}#/"{dup}#/*/!/$;/q{exch}#/x ; {/J q #}#/.{/T q #}#{stringwidth}#{}#{}# 14 string dup dup dup

It's possible for Perl programmers 

to write messy programs.

/;{}def/#{def}def/$_={/Times­Boldexchselectfont}#/_{  rmoveto} #/"{dup}#/*/!/$;/q{exch}#/x ; {/J q #}#/.{/T q #}#{stringwidth}#{}#{}# 14 string dup dup dup260 40 moveto 90 rotate ; %/}};$0='"\e[7m \e[0m"';@ARGV=split//,reverseq(ThePerl). q(Journal) x 220 ; q ; 0 T putinterval exch 7 J putinterval ; ; $_= q /m$ pop T($*!$"=!$ " )pop " * true% ? $ " $!" "  !!  !! % !" !"    !! charpath {!"""}pop $ pop{""!}pop ! neg{!#}pop 220 ! neg _{!!}pop J false %Tcharpath  clip " pop 0 " moveto 6{!!}pop $_= 105{!!}pop {$ ! $ " !  #! ##}pop{dup dup $ ! " pop pop q{"}pop 22{dup show}repeat {"}pop q 22 mul{$ "} popneg{!#! $ "}pop ! 8 .65 mul{$ # # $}pop ! neg{"}pop  _ pop{"}pop } repeat pop" {  $ " ! ! ! $ " ! !" "#"  #"!"""""! #" " # "m/;@ARGV=(@ARGV[­14..­1])x50;q} 0 "%};s/m[ou]|[­\dA­ln­z.\n_{}]|\$_=//gx;s/(.)(?{$*=''})/('$*.='.(++$#%2?'':"$0;").'pop;')x(ord($1)­31).'$*'/gee;s/((.(\e\[.m)*|.){77})/$1\n/g;print;                 sub showpage {}@P=split//,".URRUU\c8R";@d=split//,"\nrekcah xinU / lreP rehtona tsuJ";sub p{@p{"r$p","u$p"}=(P,P);pipe"r$p","u$p";++$p;($q*=2)+=$f=!fork;map{$P=$P[$f^ord($p{$_})&6];$p{$_}=/ ^$P/ix?$P:close$_}keys%p}p;p;p;p;p;map{$p{$_}=~/^[P.]/&&close$_}%p;wait until$?;map{/^r/&&<$_>}%p;$_=$d[$q];sleep rand(2)if/\S/;print#:: ::­| ::­| .­. :||­:: 0­| .­| ::||­| .:|­. :||open(Q,$0);while(<Q>){if(/^#(.*)$/){for(split('­',$1)){$q=0;for(split){s/\|/:.:/xg;s/:/../g;$Q=$_?length:$_;$q+=$q?$Q:$Q*20;}print chr($q);}}}print"\n";#.: ::||­| .||­| :|||­| ::||­| ||­:: :|||­| .:|/;{}def/#{def}def/$_={/Times­Bold exch selectfont}#/_{rmoveto}#/"{dup}#/*/!/$;/q{exch}#/x ; {/J q #}#/.{/T q #}#{stringwidth}#{}#{}# 14 string dup dup dup

It's possible for Perl programmers 

to write messy programs.

In case you hadn't 

noticed.

/;{}def/#{def}def/$_={/Times­Boldexchselectfont}#/_{  rmoveto} #/"{dup}#/*/!/$;/q{exch}#/x ; {/J q #}#/.{/T q #}#{stringwidth}#{}#{}# 14 string dup dup dup260 40 moveto 90 rotate ; %/}};$0='"\e[7m \e[0m"';@ARGV=split//,reverseq(ThePerl). q(Journal) x 220 ; q ; 0 T putinterval exch 7 J putinterval ; ; $_= q /m$ pop T($*!$"=!$ " )pop " * true% ? $ " $!" "  !!  !! % !" !"    !! charpath {!"""}pop $ pop{""!}pop ! neg{!#}pop 220 ! neg _{!!}pop J false %Tcharpath  clip " pop 0 " moveto 6{!!}pop $_= 105{!!}pop {$ ! $ " !  #! ##}pop{dup dup $ ! " pop pop q{"}pop 22{dup show}repeat {"}pop q 22 mul{$ "} popneg{!#! $ "}pop ! 8 .65 mul{$ # # $}pop ! neg{"}pop  _ pop{"}pop } repeat pop" {  $ " ! ! ! $ " ! !" "#"  #"!"""""! #" " # "m/;@ARGV=(@ARGV[­14..­1])x50;q} 0 "%};s/m[ou]|[­\dA­ln­z.\n_{}]|\$_=//gx;s/(.)(?{$*=''})/('$*.='.(++$#%2?'':"$0;").'pop;')x(ord($1)­31).'$*'/gee;s/((.(\e\[.m)*|.){77})/$1\n/g;print;                 sub showpage {}@P=split//,".URRUU\c8R";@d=split//,"\nrekcah xinU / lreP rehtona tsuJ";sub p{@p{"r$p","u$p"}=(P,P);pipe"r$p","u$p";++$p;($q*=2)+=$f=!fork;map{$P=$P[$f^ord($p{$_})&6];$p{$_}=/ ^$P/ix?$P:close$_}keys%p}p;p;p;p;p;map{$p{$_}=~/^[P.]/&&close$_}%p;wait until$?;map{/^r/&&<$_>}%p;$_=$d[$q];sleep rand(2)if/\S/;print#:: ::­| ::­| .­. :||­:: 0­| .­| ::||­| .:|­. :||open(Q,$0);while(<Q>){if(/^#(.*)$/){for(split('­',$1)){$q=0;for(split){s/\|/:.:/xg;s/:/../g;$Q=$_?length:$_;$q+=$q?$Q:$Q*20;}print chr($q);}}}print"\n";#.: ::||­| .||­| :|||­| ::||­| ||­:: :|||­| .:|/;{}def/#{def}def/$_={/Times­Bold exch selectfont}#/_{rmoveto}#/"{dup}#/*/!/$;/q{exch}#/x ; {/J q #}#/.{/T q #}#{stringwidth}#{}#{}# 14 string dup dup dup

It's possible for the programmer to make a mess of things.

It's possible for Perl programmers to write messy programs.

(In case you hadn't noticed.) It's also possible for Perl

programmers to write extremely clean, concise, and beautiful programs.

The very fact that it's possible to write messy programs in Perl is also whatmakes it possible to write programs

that are cleaner in Perl than they could ever be in a language that attempts to enforce cleanliness.

Larry Wall

/;{}def/#{def}def/$_={/Times­Boldexchselectfont}#/_{  rmoveto} #/"{dup}#/*/!/$;/q{exch}#/x ; {/J q #}#/.{/T q #}#{stringwidth}#{}#{}# 14 string dup dup dup260 40 moveto 90 rotate ; %/}};$0='"\e[7m \e[0m"';@ARGV=split//,reverseq(ThePerl). q(Journal) x 220 ; q ; 0 T putinterval exch 7 J putinterval ; ; $_= q /m$ pop T($*!$"=!$ " )pop " * true% ? $ " $!" "  !!  !! % !" !"    !! charpath {!"""}pop $ pop{""!}pop ! neg{!#}pop 220 ! neg _{!!}pop J false %Tcharpath  clip " pop 0 " moveto 6{!!}pop $_= 105{!!}pop {$ ! $ " !  #! ##}pop{dup dup $ ! " pop pop q{"}pop 22{dup show}repeat {"}pop q 22 mul{$ "} popneg{!#! $ "}pop ! 8 .65 mul{$ # # $}pop ! neg{"}pop  _ pop{"}pop } repeat pop" {  $ " ! ! ! $ " ! !" "#"  #"!"""""! #" " # "m/;@ARGV=(@ARGV[­14..­1])x50;q} 0 "%};s/m[ou]|[­\dA­ln­z.\n_{}]|\$_=//gx;s/(.)(?{$*=''})/('$*.='.(++$#%2?'':"$0;").'pop;')x(ord($1)­31).'$*'/gee;s/((.(\e\[.m)*|.){77})/$1\n/g;print;                 sub showpage {}@P=split//,".URRUU\c8R";@d=split//,"\nrekcah xinU / lreP rehtona tsuJ";sub p{@p{"r$p","u$p"}=(P,P);pipe"r$p","u$p";++$p;($q*=2)+=$f=!fork;map{$P=$P[$f^ord($p{$_})&6];$p{$_}=/ ^$P/ix?$P:close$_}keys%p}p;p;p;p;p;map{$p{$_}=~/^[P.]/&&close$_}%p;wait until$?;map{/^r/&&<$_>}%p;$_=$d[$q];sleep rand(2)if/\S/;print#:: ::­| ::­| .­. :||­:: 0­| .­| ::||­| .:|­. :||open(Q,$0);while(<Q>){if(/^#(.*)$/){for(split('­',$1)){$q=0;for(split){s/\|/:.:/xg;s/:/../g;$Q=$_?length:$_;$q+=$q?$Q:$Q*20;}print chr($q);}}}print"\n";#.: ::||­| .||­| :|||­| ::||­| ||­:: :|||­| .:|/;{}def/#{def}def/$_={/Times­Bold exch selectfont}#/_{rmoveto}#/"{dup}#/*/!/$;/q{exch}#/x ; {/J q #}#/.{/T q #}#{stringwidth}#{}#{}# 14 string dup dup dup

It's possible for the programmer to make a mess of things.

It's possible for Perl programmers to write messy programs.

(In case you hadn't noticed.) It's also possible for Perl

programmers to write extremely clean, concise, and beautiful programs.

The very fact that it's possible to write messy programs in Perl is also whatmakes it possible to write programs

that are cleaner in Perl than they could ever be in a language that attempts to enforce cleanliness.

Larry Wall

Disclaimer

<<Your favourite language>> is probably very nice too

Every language makes different trade­offs with readability

This is (mainly) about Perl's

&$%@!

                      Sigils...

Hungarian Notation

$one

@many

%dictionary

Constructing Strings

In a VB­like syntax "First: " + first + " Last: " + last + vbCrLf + "Age: " + age

Constructing Strings

In Perl, with interpolation "First: $first Last: $last\nAge: $age"

Constructing Strings

In Perl, with interpolation "First: ${first} Last: ${last}\nAge: ${age}"

More template-like

Constructing Strings

In Perl, with interpolation "First: ${first} Last: ${last}\nAge: ${age}"

Don't like the “\n” ?

Constructing Strings

Perl has multiline strings And HERE-DOCs.

my $x = <<“STRING”;First: ${first} Last: ${last}Age: ${age}STRING

Constructing Strings

Embed quotes in other languages “Is this \“readable\”?” “Is this “”better“”?”

Constructing Strings

Embed quotes in Perl 'This is “readable”'

Constructing Strings

Embed quotes in Perl 'This is “readable”' “This isn't too bad either”

Constructing Strings

Embed quotes in Perl 'This is “readable”' “This isn't too bad either” q{ And isn't this “cool”? }

Constructing String Lists

my @list = ( “one”, “two”, “three” “, ... d'oh!

Constructing String Lists

my @list = qw( one two three four five six );

qw() separated lists are easier to write at least...

There's more than one way to do it

Conditionals

if ( $age < 18 ) { ...

if ( ! $age < 18 ) { ...

Conditionals

if ( $age < 18 ) { ...

unless ( $age < 18 ) { ...

Conditionals

if ( $age < 18 ) { ...

unless ( $age < 18 ) { ...

print “Over 18s only”if $age < 18;

Conditionals

if ( $age < 18 ) { ...

unless ( $age < 18 ) { ...

print “Over 18s only”if $age < 18;

print “Over 18s only”unless $age >= 18;

Synonyms

Functionality? Readability

Booleans

or

||

Booleans

or

||

Both mean same thing... But have different precedence 'or' has lowest precedence of any operator

Booleans

<<any expression>> or <<fail>>;

Booleans

<<any expression>> or <<fail>>;

open my $FILEHANDLE, '<', # for reading $filename or die “Couldn't open ${filename}: $!”;

The unspeakable horror... regexes

Regexes

Not just Perl Perl just handles them very well

Regexes

How do you break up a string?

Regexes

How do you break up a string? Hack at it with INSTR()

Regexes

How do you break up a string? Hack at it with INSTR() Regexes

Regexes

How do you break up a string? Hack at it with INSTR() Regexes Parser

Parse::RecDescent, HOP::Parser

Regexes

How do you break up a string? Hack at it with INSTR() Regexes Parser

Parse::RecDescent, HOP::Parser Data structure parser

XML (RSS/XPath etc.), MIME, iCal etc.

Regexes

How do you break up a string? Regexes often hit the sweet spot...

...but they can get ugly when they're not the right tool for the job

Regexes

Perl regexes are builtin No need to

Compile(),  .Excecute(),  iterate through MatchCollection objects...

Regexes

Perl regexes are builtin my ($first, $last) =

$name =~ /(\w+) (\w+)/;

Regexes

Perl regexes are builtin my ($first, $last) =

$name =~ /(\w+) (\w+)/;

Other languages use strings: “(\\w+) (\\w+)” “\”\\w+\””

Regexes

Perl regexes are builtin my ($first, $last) =

$name =~ /(\w+) (\w+)/;

Other languages use strings “(\\w+) (\\w+)” “\”\\w+\””

All Perl's quoting goodness $url =~ s{^http://} {};

Regexes

Complex regexes are hard to read?

Regexes

Complex regexes are hard to read? Comment!

$_ =~ m/^ # anchor at beginning of line The\ quick\ (\w+)\ fox # fox adjective \ (\w+)\ over # fox action verb \ the\ (\w+) dog # dog adjective (?: # whitespace-trimmed comment: \s* \# \s* # whitespace and comment (.*?) # captured comment text; # (non-greedy!) \s* # any trailing whitespace )? # this is all optional $ # end of line anchor /x; # allow whitespace

Regexes

Named capture in 5.10 /(?<first>\w+) (?<last>\w+)/

            Data Structures

Data Structures

Perl is: Dynamic expression­based

Data Structures

Perl is: Dynamic expression­based

Can declare most data­structures trivially at runtime.

Data Structures

Declare most data­structures trivially at runtime.

my $person = { name => { first => 'Fred', last => 'Bloggs', }, age => 12, hobbies => [qw/ origami windsurfing /], };

Data Structures http://igoro.com/archive/7-tricks-to-simplify-your-programs-with-linq/#Tip1

C# with Linq int[] a = Enumerable.Repeat (-1, 10).ToArray();

int[] b = Enumerable.Range (0, 10).ToArray()

Data Structures http://igoro.com/archive/7-tricks-to-simplify-your-programs-with-linq/#Tip1

C# with Linq int[] a = Enumerable.Repeat (-1, 10).ToArray();

int[] b = Enumerable.Range (0, 10).ToArray()

“Elegant”

Data Structures http://igoro.com/archive/7-tricks-to-simplify-your-programs-with-linq/#Tip1

C# with Linq int[] a = Enumerable.Repeat (-1, 10).ToArray();

int[] b = Enumerable.Range (0, 10).ToArray()

“Elegant” Perl:

my @a = (-1) x 10; my @b = (0..10);

Data Structures http://igoro.com/archive/7-tricks-to-simplify-your-programs-with-linq/#Tip1

C# with Linq is elegant compared to: int[10] b;for (i=0; i<10; i++) { b[i] = i;}

Data Structures http://igoro.com/archive/7-tricks-to-simplify-your-programs-with-linq/#Tip1

C# with Linq is elegant compared to: int[10] b;for (i=0; i<10; i++) { b[i] = i;}

This is really the functional vs. imperative debate

Functional Programming

Perl is not a functional programming language Borrows some functional features

Functional Programming

Filter @recent = grep {

$_->sent > ($today – ONE_DAY)}@emails;

Functional Programming

Transform @full_names = map {

“$_->{first} $_->{last”}@people;

Functional Programming

A handful of other functions... sort join

Functional Programming

...and modules use List::Util 'sum';print sum(1..10);

Functional Programming

...and first class functions sub double { return 2 * shift } sub triple { return 3 * shift } my %dispatch = (

double => \&double,triple => \&triple,

); my $result = $dispatch{$command}->( $input );

Functional Programming

...including anonymous functions my %dispatch = (

double => sub { 2 * shift },triple => sub { 3 * shift },

)

Functional Programming

...and syntactic sugar my @doubled = map { 2 * $_ } @nums;

First class functions

Enable metaprogramming (OK, there's eval too... if you really need it)

First class functions

Typical cached subroutine

sub my_query {    my ($self, %params) = @_;    my $cache = $self­>get_cache;    my $key = $self­>get_key( %params );    my $result;    return $result if $result = $cache­>get($key);    $result = $self­>expensive_operation(%params);    # additional processing    $cache­>set($key, $result, 20);    return $result;}

First class functions

Typical cached subroutine

sub my_query {    my ($self, %params) = @_;    

    my $result                = $self­>expensive_operation(%params);    # additional processing

    return $result;}

First class functions

Turn this second into the first my $cached_query =

cache(\&query, %params);

Optionally, install it in the symbol table *query = $cached_query;

Or add syntactic sugar! sub my_query :Cached(time=>20) {

my $result = $self->expensive_operation;# additional processing

return $result;}

Working hard so you don't have to

Caching module

Attribute::Cached Unreleased but see Memoize package table hackery

(manual, but see Class::MOP) Attribute parsing (using Attribute::Handlers)

Surprising fact

Perl programmers are (at best) obsessive about syntax and readable code

Moose

Møøse

Built on scary crack (Class::MOP) http://moose.perl.org/

http://www.iinteractive.com/moose/

Møøse

package Point; use Moose; # automatically turns on strict and warnings

has 'x' => (is => 'rw', isa => 'Int'); has 'y' => (is => 'rw', isa => 'Int');

sub clear { my $self = shift; $self->x(0); $self->y(0); }

Møøse

package Point3D; use Moose;

extends 'Point';

has 'z' => (is => 'rw', isa => 'Int');

after 'clear' => sub { my $self = shift; $self->z(0); };

Møøse

Not just syntactic sugar (Post)modern OO

composition with roles

Møøse - example

HTTP request class package Request; use Moose; use Moose::Util::TypeConstraints; use HTTP::Headers (); use Params::Coerce (); use URI ();

has 'base' => (is => 'rw', isa => 'Uri', coerce => 1); has 'uri' => (is => 'rw', isa => 'Uri', coerce => 1); has 'method' => (is => 'rw', isa => 'Str'); has 'protocol' => (is => 'rw', isa => 'Protocol'); has 'headers' => ( is => 'rw', isa => 'Header', coerce => 1, default => sub { HTTP::Headers->new } );

Møøse - example

Hey!  Types!

subtype 'Header' => as 'Object' => where { $_->isa('HTTP::Headers') };

subtype 'Protocol' => as Str => where { /^HTTP\/[0-9]\.[0-9]$/ };

subtype 'Uri' => as 'Object' => where { $_->isa('URI') };

Møøse - example

Coercions working to make using the code easier

coerce 'Uri' => from 'Object' => via { $_->isa('URI') ? $_ : Params::Coerce::coerce( 'URI', $_ ) } => from 'Str' => via { URI->new( $_, 'http' ) };

Thank you

References perl.com/pub/a/1999/03/pm.html

perl.com/pub/a/2004/01/16/regexps.html

igoro.com/archive/7­tricks­to­simplify­your­programs­with­linq/

moose.perl.org/

blog.timbunce.org/2008/03/08/perl­myths/

Pictures “Larry Wall” by Michael McCracken

flickr.com/photos/michaelmccracken/540924868/

Obfus (BooK, mjd, Les Peters)

“Donald Duck” (Disney)

“Screwdrivers” by ladyheart morguefile.com/archive/?display=134240&

“Horror Masks” by xeniamorguefile.com/archive/?display=93245&

“Swimming Duck" by Yael Lewenstein flickr.com/photos/yaellebel

“Moose” by steve took it flickr.com/photos/stevewall/290510690/

Recommended