currying in perl

Post on 11-Jun-2015

2.399 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

http://www.slideshare.net/hiratara/hokkaidopm-17020206 の本物の方。

TRANSCRIPT

CurryとHokkaido.pm2013.3.9 hiratara

FreakOut

初代ベストエルティニスト賞

“Hokkaido.pm Casual はじめました” by techno_neko

スープCurryが観客の心と胃袋をつかみ、初代ベストエルティニスト賞となりました!おめでとうございました!http://hachiojipm.org/?p=403

“Hokkaido.pm Casual はじめました” by techno_neko

スープCurryが観客の心と胃袋をつかみ、初代ベストエルティニスト賞となりました!おめでとうございました!http://hachiojipm.org/?p=403

Curryがウケるっぽい

currying

カリー化とは

• A × B→Cの関数を、A→(B→C)にする

• hoge($x, $y) みたいな関数をcurried_hoge($x)($y) みたいにする

カリー化と部分適用は違うよ

部分適用とは

• A × B→Cの関数を、B→Cにする

• hoge($x, $y) みたいな関数に3を適用してhoge_3($y) みたいにする

誤用すると色々危ない

curry関数の実装sub curry { my $f = shift; sub { my $x = shift; sub { $f->($x, @_) }; };}

再帰的にカリー化• hoge($x, $y, $z) みたいな関数は

curried_hoge($x)($y, $z) じゃなくcurried_hoge($x)($y)($z) みたいにしたい

• A × B × C→DA→(B × C→D)A→(B→(C→D))

curry_n関数の実装sub curry_n { my ($n, $f) = @_; $n <= 1 ? $f : sub { my $x = shift; my $fx = curry($f)->($x); curry_n($n - 1, $fx); };}

curry_n関数の実装sub curry_n { my ($n, $f) = @_; $n <= 1 ? $f : sub { my $x = shift; my $fx = curry($f)->($x); curry_n($n - 1, $fx); };}

引数の個数が必要

使い方

sub add { $_[0] + $_[1] + $_[2] }

my $x = (curry_n 3, \&add)->(3)(4)(5);

使い方

sub add { $_[0] + $_[1] + $_[2] }

my $x = (curry_n 3, \&add)->(3)(4)(5);まとめたい

カレーをカレーで食べる

新しい関数を作る

*curried_curry_n = curry_n(2, \&curry_n);*curry3 = curried_curry_n(3);

my $x = curry3(\&add)->(3)(4)(5);

新しい関数を作る

*curried_curry_n = curry_n(2, \&curry_n);*curry3 = curried_curry_n(3);

my $x = curry3(\&add)->(3)(4)(5);

curry_nは2引数関数

新しい関数を作る

*curried_curry_n = curry_n(2, \&curry_n);*curry3 = curried_curry_n(3);

my $x = curry3(\&add)->(3)(4)(5);

curry_nは2引数関数

引数の数を部分適用して新しい関数にする

カリー化すると部分適用しやすい

*curry3 = curried_curry_n(3);*curry4 = curried_curry_n(4);*curry5 = curried_curry_n(5);

*{“curry$_”} = curried_curry_n($_) for 3.. 10000000;

ほんとに引数の数ってわからないの?

($$$)

I ♡ function prototyping

プロトタイプを使う

sub parse_proto ($) { my $f = shift; my $proto = prototype $f; $proto =~ /^([&_+*\$]|\\\[[\$@%&*]+\]|\\[\$@%&*])(.+)/ ? ($1, $2) : (undef, $proto);}

プロトタイプを使うsub curry_proto_n ($) { my $f = shift; my ($p, $ps) = parse_proto $f;

! $p ? $f : eval qq/sub ($p) { my \$x = shift; my \$fx = sub ($ps) { \$f->(\$x, \@_) }; curry_proto_n \$fx; }/;}

プロトタイプを使うsub curry_proto_n ($) { my $f = shift; my ($p, $ps) = parse_proto $f;

! $p ? $f : eval qq/sub ($p) { my \$x = shift; my \$fx = sub ($ps) { \$f->(\$x, \@_) }; curry_proto_n \$fx; }/;}

使い方sub add ($$$) { $_[0] + $_[1] + $_[2] }

my $x = (curry_proto_n \&add)->(3)(4)(5);

BEGIN { *add10 = (curry_proto \&add)->(10) }my $x = add10 3, 4;

使い方sub add ($$$) { $_[0] + $_[1] + $_[2] }

my $x = (curry_proto_n \&add)->(3)(4)(5);

BEGIN { *add10 = (curry_proto \&add)->(10) }my $x = add10 3, 4;

かっこなくてもよい

One more function prototyping

Pod::Functions% perl -MPod::Functions -e 'eval { print $_, "\t", +(prototype "CORE::$_"), "\n" } for keys %Flavor'...getgrgid $connect *$dbmopen \%$$link $$rand ;$dbmclose \%msgsnd $$$umask ;$sleep ;$seek *$$

currying builtins

use 5.16.2;my $x = (curry_proto_n \&CORE::substr)->("abcde")(1)(2);

BEGIN { *substr_abcde = (curry_proto \&CORE::substr)->("abcde");}my $y = substr_abcde 1, 2;

currying builtins

use 5.16.2;my $x = (curry_proto_n \&CORE::substr)->("abcde")(1)(2);

BEGIN { *substr_abcde = (curry_proto \&CORE::substr)->("abcde");}my $y = substr_abcde 1, 2;

かっこなくてもよい

まとめ

• カリー化すると部分適用しやすい

• \&CORE::xxx によりさらに便利に

• プロトタイプ使うと隣の同僚にDISられる

top related