C::P::FV::AutoのCatalyst 5.8対応パッチを書いた

typesterさん謹製のC::P::FV::Autoはとっても便利なのですが、例に漏れず5.8対応されていません。で、意外とニーズがあるようなのでさくっとpatch書いてみました。(といってもMRO::Compat化したくらいですが…)

ただ、sub forwardでlocal $NEXT::NEXT{}してるのがちと意味がわからなかったのと代替案が思いつかなかったのでざっくり削ってます。Changes見る限りnestしたforwardの対応っぽいのですが、ごめんなさい。よくわからんかったです。
一応それのテストであろう06_nexted_actions.tに通ってはいるのですが、この辺は教えてエロい人ってことでよろしくです。

初めてのDevel::BindPP

Standard C++
foo-bar.cpp

#include <iostream>

int main () {
    std::cout << "Hello World";
}
$ gcc -o foo-bar foo-bar.cpp -lstdc++
$ foo-bar
Hello Wolrd


Devel::BindPP

$ perl -MDevel::BindPP -e 'use Devel::BindPP::WriteFile()'

foo-bar.cpp

include <iostream>
#include "bindpp.h"

XS(xs_hello_world) {
    std::cout << "Hello World";
}

extern "C" {
XS(boot_Foo__Bar) {
    pl::BootstrapCtx bc;

    pl::Package pkg("Foo::Bar",  __FILE__);
    pkg.add_method("hello_world", xs_hello_world);
}
};

MakeFile.pl

use inc::Module::Install;
name 'Foo-Bar';
all_from 'lib/Foo/Bar.pm';

makemaker_args(
    OBJECT => '$(O_FILES)',
    LIBS => ['-lstdc++'],
);
WriteAll; 

lib/Foo/Bar.pm

package Foo::Bar;

use strict;
use warnings;

our $VERSION = '0.00001';

use XSLoader;
XSLoader::load __PACKAGE__, $VERSION;

1;
$ perl MakeFile.pl
$ make

$ perl -Mblib -MFoo::Bar -e 'Foo::Bar::hello_world'
HelloWorld

MooseのマニュアルとTPF

Moose Docs Grant Is Complete – House Absolute(ly) Pointless

http://cpansearch.perl.org/src/DROLSKY/Moose-0.74/Changes


0.66 Tue, February 3, 2009
* Moose::Manual
- This is a brand new, extensive manual for Moose. This aims to
provide a complete introduction to all of Moose's
features. This work was funded as part of the Moose docs grant
from TPF. (Dave Rolsky)

Moose::ManualってTPFの助成が出てたんですね。そーいえば、そうだったかも。
で、TPF-Jが助成して翻訳する流れと。なるほど。

for(;;)とforeach()とLoop unrollingと

YappoLogs: CPUの気持ちは大事だけど、VMの気持ちも考えようよ
http://d.hatena.ne.jp/yappo/20090330/1238360153

会議中なので-MO=Consiseしてないし特に言いたいことはない。

use strict;
use warnings;
use Benchmark qw(:all);

cmpthese(
    timethese(
        0,
        {
            loop_for => sub {
                my $sum = 0;
                for (my $i = 0; $i < 100; $i++) {
                    $sum = $sum + $i;
                }
            },
            loop_foreach => sub {
                my $sum = 0;
                for my $i (0 .. 99) {
                    $sum = $sum + $i;
                }
            },
            loop_unrolling_5 => sub {
                my $sum = 0;
                for (my $i = 0; $i < 100; $i += 5) {
                    $sum = $sum + $i + 0;
                    $sum = $sum + $i + 1;
                    $sum = $sum + $i + 2;
                    $sum = $sum + $i + 3;
                    $sum = $sum + $i + 4;
                }
            },
            loop_unrolling_10 => sub {
                my $sum = 0;
                for (my $i = 0; $i < 100; $i += 10) {
                    $sum = $sum + $i + 0; $sum = $sum + $i + 1; $sum = $sum + $i + 2; $sum = $sum + $i + 3; $sum = $sum + $i + 4;
                    $sum = $sum + $i + 5; $sum = $sum + $i + 6; $sum = $sum + $i + 7; $sum = $sum + $i + 8; $sum = $sum + $i + 9;
                }
            },
            loop_unrolling_50 => sub {
                my $sum = 0;
                for (my $i = 0; $i < 100; $i += 50) {
                    $sum = $sum + $i + 0; $sum = $sum + $i + 1; $sum = $sum + $i + 2; $sum = $sum + $i + 3; $sum = $sum + $i + 4;
                    $sum = $sum + $i + 5; $sum = $sum + $i + 6; $sum = $sum + $i + 7; $sum = $sum + $i + 8; $sum = $sum + $i + 9;
                    $sum = $sum + $i + 10; $sum = $sum + $i + 11; $sum = $sum + $i + 12; $sum = $sum + $i + 13; $sum = $sum + $i + 14;
                    $sum = $sum + $i + 15; $sum = $sum + $i + 16; $sum = $sum + $i + 17; $sum = $sum + $i + 18; $sum = $sum + $i + 19;
                    $sum = $sum + $i + 20; $sum = $sum + $i + 21; $sum = $sum + $i + 22; $sum = $sum + $i + 23; $sum = $sum + $i + 24;
                    $sum = $sum + $i + 25; $sum = $sum + $i + 26; $sum = $sum + $i + 27; $sum = $sum + $i + 28; $sum = $sum + $i + 29;
                    $sum = $sum + $i + 30; $sum = $sum + $i + 31; $sum = $sum + $i + 32; $sum = $sum + $i + 33; $sum = $sum + $i + 34;
                    $sum = $sum + $i + 35; $sum = $sum + $i + 36; $sum = $sum + $i + 37; $sum = $sum + $i + 38; $sum = $sum + $i + 39;
                    $sum = $sum + $i + 40; $sum = $sum + $i + 41; $sum = $sum + $i + 42; $sum = $sum + $i + 43; $sum = $sum + $i + 44;
                    $sum = $sum + $i + 45; $sum = $sum + $i + 46; $sum = $sum + $i + 47; $sum = $sum + $i + 48; $sum = $sum + $i + 49;
                }
            },
            loop_unrolling_100 => sub {
                my $sum = 0;
                for (my $i = 0; $i < 100; $i += 100) {
                    $sum = $sum + $i + 0; $sum = $sum + $i + 1; $sum = $sum + $i + 2; $sum = $sum + $i + 3; $sum = $sum + $i + 4;
                    $sum = $sum + $i + 5; $sum = $sum + $i + 6; $sum = $sum + $i + 7; $sum = $sum + $i + 8; $sum = $sum + $i + 9;
                    $sum = $sum + $i + 10; $sum = $sum + $i + 11; $sum = $sum + $i + 12; $sum = $sum + $i + 13; $sum = $sum + $i + 14;
                    $sum = $sum + $i + 15; $sum = $sum + $i + 16; $sum = $sum + $i + 17; $sum = $sum + $i + 18; $sum = $sum + $i + 19;
                    $sum = $sum + $i + 20; $sum = $sum + $i + 21; $sum = $sum + $i + 22; $sum = $sum + $i + 23; $sum = $sum + $i + 24;
                    $sum = $sum + $i + 25; $sum = $sum + $i + 26; $sum = $sum + $i + 27; $sum = $sum + $i + 28; $sum = $sum + $i + 29;
                    $sum = $sum + $i + 30; $sum = $sum + $i + 31; $sum = $sum + $i + 32; $sum = $sum + $i + 33; $sum = $sum + $i + 34;
                    $sum = $sum + $i + 35; $sum = $sum + $i + 36; $sum = $sum + $i + 37; $sum = $sum + $i + 38; $sum = $sum + $i + 39;
                    $sum = $sum + $i + 40; $sum = $sum + $i + 41; $sum = $sum + $i + 42; $sum = $sum + $i + 43; $sum = $sum + $i + 44;
                    $sum = $sum + $i + 45; $sum = $sum + $i + 46; $sum = $sum + $i + 47; $sum = $sum + $i + 48; $sum = $sum + $i + 49;
                    $sum = $sum + $i + 50; $sum = $sum + $i + 51; $sum = $sum + $i + 52; $sum = $sum + $i + 53; $sum = $sum + $i + 54;
                    $sum = $sum + $i + 55; $sum = $sum + $i + 56; $sum = $sum + $i + 57; $sum = $sum + $i + 58; $sum = $sum + $i + 59;
                    $sum = $sum + $i + 60; $sum = $sum + $i + 61; $sum = $sum + $i + 62; $sum = $sum + $i + 63; $sum = $sum + $i + 64;
                    $sum = $sum + $i + 65; $sum = $sum + $i + 66; $sum = $sum + $i + 67; $sum = $sum + $i + 68; $sum = $sum + $i + 69;
                    $sum = $sum + $i + 70; $sum = $sum + $i + 71; $sum = $sum + $i + 72; $sum = $sum + $i + 73; $sum = $sum + $i + 74;
                    $sum = $sum + $i + 75; $sum = $sum + $i + 76; $sum = $sum + $i + 77; $sum = $sum + $i + 78; $sum = $sum + $i + 79;
                    $sum = $sum + $i + 80; $sum = $sum + $i + 81; $sum = $sum + $i + 82; $sum = $sum + $i + 83; $sum = $sum + $i + 84;
                    $sum = $sum + $i + 85; $sum = $sum + $i + 86; $sum = $sum + $i + 87; $sum = $sum + $i + 88; $sum = $sum + $i + 89;
                    $sum = $sum + $i + 90; $sum = $sum + $i + 91; $sum = $sum + $i + 92; $sum = $sum + $i + 93; $sum = $sum + $i + 94;
                    $sum = $sum + $i + 95; $sum = $sum + $i + 96; $sum = $sum + $i + 97; $sum = $sum + $i + 98; $sum = $sum + $i + 99;
                }
            },
            noloop => sub {
                my $sum = 0;
                $sum = $sum + 0; $sum = $sum + 1; $sum = $sum + 2; $sum = $sum + 3; $sum = $sum + 4;
                $sum = $sum + 5; $sum = $sum + 6; $sum = $sum + 7; $sum = $sum + 8; $sum = $sum + 9;
                $sum = $sum + 10; $sum = $sum + 11; $sum = $sum + 12; $sum = $sum + 13; $sum = $sum + 14;
                $sum = $sum + 15; $sum = $sum + 16; $sum = $sum + 17; $sum = $sum + 18; $sum = $sum + 19;
                $sum = $sum + 20; $sum = $sum + 21; $sum = $sum + 22; $sum = $sum + 23; $sum = $sum + 24;
                $sum = $sum + 25; $sum = $sum + 26; $sum = $sum + 27; $sum = $sum + 28; $sum = $sum + 29;
                $sum = $sum + 30; $sum = $sum + 31; $sum = $sum + 32; $sum = $sum + 33; $sum = $sum + 34;
                $sum = $sum + 35; $sum = $sum + 36; $sum = $sum + 37; $sum = $sum + 38; $sum = $sum + 39;
                $sum = $sum + 40; $sum = $sum + 41; $sum = $sum + 42; $sum = $sum + 43; $sum = $sum + 44;
                $sum = $sum + 45; $sum = $sum + 46; $sum = $sum + 47; $sum = $sum + 48; $sum = $sum + 49;
                $sum = $sum + 50; $sum = $sum + 51; $sum = $sum + 52; $sum = $sum + 53; $sum = $sum + 54;
                $sum = $sum + 55; $sum = $sum + 56; $sum = $sum + 57; $sum = $sum + 58; $sum = $sum + 59;
                $sum = $sum + 60; $sum = $sum + 61; $sum = $sum + 62; $sum = $sum + 63; $sum = $sum + 64;
                $sum = $sum + 65; $sum = $sum + 66; $sum = $sum + 67; $sum = $sum + 68; $sum = $sum + 69;
                $sum = $sum + 70; $sum = $sum + 71; $sum = $sum + 72; $sum = $sum + 73; $sum = $sum + 74;
                $sum = $sum + 75; $sum = $sum + 76; $sum = $sum + 77; $sum = $sum + 78; $sum = $sum + 79;
                $sum = $sum + 80; $sum = $sum + 81; $sum = $sum + 82; $sum = $sum + 83; $sum = $sum + 84;
                $sum = $sum + 85; $sum = $sum + 86; $sum = $sum + 87; $sum = $sum + 88; $sum = $sum + 89;
                $sum = $sum + 90; $sum = $sum + 91; $sum = $sum + 92; $sum = $sum + 93; $sum = $sum + 94;
                $sum = $sum + 95; $sum = $sum + 96; $sum = $sum + 97; $sum = $sum + 98; $sum = $sum + 99;
                }
        }
    )
);
Benchmark: running loop_for, loop_foreach, loop_unrolling_10, loop_unrolling_100, loop_unrolling_5, loop_unrolling_50, noloop for at least 3 CPU seconds...
  loop_for:  3 wallclock secs ( 3.16 usr +  0.00 sys =  3.16 CPU) @ 41487.34/s (n=131100)
loop_foreach:  3 wallclock secs ( 3.17 usr +  0.00 sys =  3.17 CPU) @ 53420.19/s (n=169342)
loop_unrolling_10:  3 wallclock secs ( 3.14 usr +  0.00 sys =  3.14 CPU) @ 42575.48/s (n=133687)
loop_unrolling_100:  4 wallclock secs ( 3.14 usr +  0.00 sys =  3.14 CPU) @ 43949.04/s (n=138000)
loop_unrolling_5:  3 wallclock secs ( 3.09 usr +  0.00 sys =  3.09 CPU) @ 37364.72/s (n=115457)
loop_unrolling_50:  3 wallclock secs ( 3.13 usr +  0.00 sys =  3.13 CPU) @ 44089.46/s (n=138000)
    noloop:  4 wallclock secs ( 3.21 usr +  0.00 sys =  3.21 CPU) @ 96098.44/s (n=308476)
                      Rate loop_unrolling_5 loop_for loop_unrolling_10 loop_unrolling_100 loop_unrolling_50 loop_foreach noloop
loop_unrolling_5   37365/s               --     -10%              -12%               -15%              -15%         -30%   -61%
loop_for           41487/s              11%       --               -3%                -6%               -6%         -22%   -57%
loop_unrolling_10  42575/s              14%       3%                --                -3%               -3%         -20%   -56%
loop_unrolling_100 43949/s              18%       6%                3%                 --               -0%         -18%   -54%
loop_unrolling_50  44089/s              18%       6%                4%                 0%                --         -17%   -54%
loop_foreach       53420/s              43%      29%               25%                22%               21%           --   -44%
noloop             96098/s             157%     132%              126%               119%              118%          80%     --

ソースフィルタを使わないでtry/catchを提供してくれるTryCatch

http://marcus.nordaaker.com/2009/03/a-proper-trycatch-for-perl/

メモ 後で書く

{
    package HTTPStatus;
    use Moose;
    has code => (is => 'rw', isa => 'Int', required => 1);
    __PACKAGE__->meta->make_immutable;
}

use strict;
use warnings;

use TryCatch;

sub foo {
    my $code = shift;

    try {
        die HTTPStatus->new(code => $code);
    } catch (HTTPStatus $e where {$_->code >= 400 && $_->code < 500}) {
        return '4xx client error';
    } catch (HTTPStatus $e where {$_->code >= 500 && $_->code < 600}) {
        return '5xx server error';
    } catch (HTTPStatus $e where {$_->code < 200 || $_->code >= 600}) {
        return 'Unknown error';
    }
    return 'ok';
}

warn foo(200); #ok         
warn foo(500); #'5xx server error

Delegationを使わないでNon-Mooseクラスを継承

FAQにもあるけど、Moose::Objectも継承して->meta->new_objectを明示的に呼ぶことにより、delegationを使わないでNon-Mooseクラスを継承することもできる。

use strict;
use warnings;
{
    package Parent;
    
    sub new {
        my ($class, %args) = @_;
        
        bless {name => $args{name}}, $class;
    }
}
 
{
 
    package Child;
 
    use Moose;
    extends qw(Parent Moose::Object);
    no Moose;
 
    sub new {
        my $class = shift;
        my $obj = $class->SUPER::new(@_);
        return $class->meta->new_object(
            __INSTANCE__ => $obj,
            @_,
        );
    }
 
    __PACKAGE__->meta->make_immutable;
}
 
my $obj = Child->new(name => 'foo');
warn $obj->{name};

こんな感じだけど、Parentがuse fieldsしてる場合にはやっぱりdelegationを使わないとダメなそうだ。

use strict;
use warnings;
{
    package Parent;
    use fields qw(name);
 
    sub new {
        my ($class, %args) =@_;
        my $self = ref $class ? $class : fields::new($class);
        $self->{name} = $args{name};
        $self;
    }
}
...

こんな感じにParentがuse fieldsしてると

Pseudo-hashes are deprecated at subclass.pl line 10.
No such pseudo-hash field "name" at subclass.pl line 10.

と怒られる。
jrockway曰くfieldsの非互換性をMooseで知る術がないからだそうな。
ぶっちゃけfieldsが何やってんのかよくわかってないのでそーゆーもんだと覚えた。

Non-MooseクラスをDelegationを使って継承

久々にMoose書こうとしたら酷いことになってたのでリハビリ開始。
Non-Mooseなクラスを継承する時には委譲を使うのは知ってたけどコンストラクタも継承するとこんな感じ?
自信なす><

{
    package Parent;

    use strict;
    use warnings;

    sub new {
        my ($class, %args) = @_;
        bless {%args}, $class;
    }

    sub name {
        my ($self, $name) = @_;
        $self->{name} = $name if $name;
        return $self->{name};
    }

    package Child;

    use Moose;

    has parent => (
        is      => 'ro',
        isa     => 'Parent',
        handles => [qw/name/],
    );

    no Moose;

    sub BUILDARGS {
        my ($class, %args) = @_;

        $args{parent} = Parent->new(%args);

        return {%args};
    }

    __PACKAGE__->meta->make_immutable;
}

my $child = Child->new(name => 'hoge');
warn $child->name;