Created: 2016-08-31 Wed 16:53
https://github.com/zakame/fp-perl-talk
my $item = "a single item";
my @array = ("one", "two", "many", "items"); # ordered list
my %hash = ( x => "y", a => '1' ); # key-value pairs
my $array_ref = \@array;
my $hash_ref = \%hash;
sub my_function {
my $input = shift;
"return $input as part of a string";
}
my $code_ref = \&my_function;
use feature 'say'; # like `print`, but with trailing newline
say my_function($item);
say my_function($array_ref);
say $code_ref->($hash_ref);
return a single item as part of a string return ARRAY(0x2223520) as part of a string return HASH(0x22235c8) as part of a string
sub factorial {
my $n = shift; # accepts a number
return 1 if $n == 1; # stop recursing on this condition
$n * factorial( $n - 1 ); # otherwise do it
}
use feature 'say';
say factorial(5);
say factorial(10);
120 3628800
sub factorial_r {
my $n = shift;
return 1 if $n == 1;
$n * factorial_r( $n - 1 );
}
sub factorial_i {
my $n = shift;
$n *= $n - 1 for reverse 1 .. $n;
$n;
}
use Benchmark 'cmpthese';
cmpthese(
1000000,
{ recursive => 'factorial_r(10)',
iterative => 'factorial_i(10)',
}
);
Rate recursive iterative recursive 416667/s -- -53% iterative 884956/s 112% --
# I'm lazy, use a web framework!
use Mojolicious::Lite;
sub index {
my $c = shift;
$c->render( text => "You've reached the index." );
}
get '/' => \&index;
# "sub { ... }" is an anonymous code ref
get '/:foo' => sub {
my $c = shift;
my $foo = $c->param('foo');
$c->render( text => "Hello from $foo!" );
};
app->start;
use feature 'say';
use File::Find;
sub wanted {
# predicate/filter for files to search
/.*zakame.*/ && # find files with `zakame` in the name
int( -M _ ) > 2 && # that's older than 2 days
say;
}
# search the wastebasket
find( \&wanted, '/tmp' );
.zakame-seamonkey-x7y0k6u4.default .zakame-google-chrome zakame-google-chrome http_cheesecake.zakame.org_0.localstorage http_cheesecake.zakame.org_0.localstorage-journal .zakame-firefox-33zz2l6v.default
Before Perl v5.10 and the state
keyword, closures were a way of
doing static
variables:
$count = 1; # a global variable
# explicitly make a new scope with a block:
{
my $count = 1; # a lexically-scoped variable
sub counter { $count++ } # a closure incrementing my $count
}
use feature 'say';
say "lexical variable \$count = ", counter for 1..3;
say "global variable \$count = $count";
lexical variable $count = 1 lexical variable $count = 2 lexical variable $count = 3 global variable $count = 1
sub make_bean_counter {
my ( $start, $callback ) = @_; # accept a starting value and a callback
sub {
# return a new function that increments and calls back
$start++;
$callback->($start);
};
}
my $from_ten = make_bean_counter( 10, sub { print $_[0], "\n"; } );
$from_ten->() for 1..3; # go from 10 to 13
my $sum;
sub accumulate {
$sum += $_[0]
}
my $from_50 = make_bean_counter( 50, \&accumulate );
$from_50->() for 1..5; # total from 51 to 55
print $sum;
11 12 13 265
use HTTP::Status ':constants';
my $app = sub {
my $env = shift;
+[ HTTP_OK,
[ 'Content-Type' => 'text/html' ],
["Hello, $env->{REMOTE_ADDR}"]
];
};
use Plack::Builder;
builder {
# external middleware currying the pipeline to $app
enable "Debug", panels => [qw(Memory Timer)];
# inline middle doing explicit currying
enable sub {
my $app = shift;
sub {
my $env = shift;
# override REMOTE_ADDR
$env->{REMOTE_ADDR} = '67.202.105.161';
$app->($env);
};
};
$app;
};
From http://www.perl.com/pub/2006/01/05/parsing.html
use HOP::Lexer 'make_lexer';
my @sql = $sql;
my $lexer = make_lexer(
sub { shift @sql },
[ 'KEYWORD', qr/(?i:select|from|as)/ ],
[ 'COMMA', qr/,/ ],
[ 'OP', qr{[-=+*/]} ],
[ 'PAREN', qr/\(/, sub { [shift, 1] } ],
[ 'PAREN', qr/\)/, sub { [shift, -1] } ],
[ 'TEXT', qr/(?:\w+|'\w+'|"\w+")/, \&text ],
[ 'SPACE', qr/\s*/, sub {} ],
);
sub text {
my ($label, $value) = @_;
$value =~ s/^["']//;
$value =~ s/["']$//;
return [ $label, $value ];
}
Snippet adapted from my Hashids Perl module:
package My::Hashids;
use Moo;
use Carp;
# A salt is needed to initialize the Hashids encoder
has salt => ( is => 'ro', default => '');
# A minimum hash length is also needed
has minHashLength => (
is => 'ro',
isa => sub {
croak "$_[0] is not a number!" unless $_[0] =~ /^\d+$/;
},
default => 0,
);
has alphabet => (
is => 'rw',
default => sub { join '' => 'a' .. 'z', 'A' .. 'Z' },
);