ishiducaの日記 このページをアンテナに追加 RSSフィード

2011-11-28

[]"Deep recursion on anonymous subroutine" 19:52 "Deep recursion on anonymous subroutine" - ishiducaの日記 を含むブックマーク はてなブックマーク - "Deep recursion on anonymous subroutine" - ishiducaの日記 "Deep recursion on anonymous subroutine" - ishiducaの日記 のブックマークコメント

合成関数を作る compose 関数を実装しようとして $f = sub { $f->($g->(@_)) } としたら、"Deep recursion on anonymous subroutine" と怒られた

use strict;
use warnings;
use feature qw(say);

sub inc {    my $x = shift; $x + 1; }
sub double { my $x = shift; $x * 2; }
sub square { my $x = shift; $x * $x; }

sub compose {
    my $first = pop @_;
    while (my $g = pop @_) {
        # こうすると "Deep recursion on anonymous subroutine" と警告を出して無限ループしちゃう
        $first = sub { $first->($g->(@_)) };
    }
    $first;
}
my $ids = compose(\&inc, \&double, \&square);
my $sdi = compose(\&square, \&double, \&inc);

say $ids->(3);
say $sdi->(3);

なのでループの代わりに再帰させる

sub compose {
    my $f = pop @_;
    my $g;

    ($g = pop @_)
        ? compose(@_, sub { $f->($g->(@_)) })
        : $f;
}

my $ids = compose(\&inc, \&double, \&square);
my $sdi = compose(\&square, \&double, \&inc);

ただ、最初の compose もあっさり抜けられて

sub compose {
    my $first = pop @_;
    while (my $g = pop @_) {
        my $f = $first; # $f に代入するだけ
        $first = sub { $f->($g->(@_)) };
    }
    $first;
}
my $ids = compose(\&inc, \&double, \&square);
my $sdi = compose(\&square, \&double, \&inc);

say $ids->(3); # 64
say $sdi->(3); # 19

焦ったのでメモ

ゲスト



トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20111128