Perl ã®ãªã¹ãæä½ã Ruby 風ã«
Perl ã®è¨èªçµã¿è¾¼ã¿ã®ãªã¹ãæä½ã¯é¢æ°å½¢å¼ã§ãpush(@array, 1, 2) ã®ãããªè¨è¿°ã«ãªãã¾ããä¸ã¤ã®ãªã¹ãã«å¯¾ãã¦è¤æ°ã®æä½ããããå ´åãªã©ã¯ãé¢æ°å¼ã³åºããè¤æ°è¡ã«ããã£ã¦æ¸ãã¦ãããã¨ã«ãªããå°ã é¢åã§ããããã Perl ã¯ãPerl ã®ãªã¹ãå®è£ ã§ããé åã®ãªãã¡ã¬ã³ã¹ã« bless ãã¦ã¡ã½ãããå®ç¾©ããã¯ã©ã¹ãä½ããã¨ãã§ãã¾ãããã®ç¬èªã«å®ç¾©ããã¯ã©ã¹ã«ããªããã£ããªæä½ãå ãã¦ãã£ã¦ãRuby ã®ããã«é£ç¶ããã¡ã½ããã®å¼ã³åºãã«ãããªã¹ãæä½ãå®ç¾ãããã¨ãå¯è½ã§ãã
ããã§ã¯ List::RubyLike ã¨ããé åã¯ã©ã¹ãä½æãã¾ããã¾ãã¯æå§ãã«é åã« bless ãã¦ãsize() ã¡ã½ãããå¼ã³åºããããã«ãã¾ãã以ä¸ã®ããã«ãªãã¾ãã
package List::RubyLike; use strict; use warnings; sub new { my ($self, @list) = @_; my $class = ref $self || $self; bless \@list, $class; } sub size { my $self = shift; scalar @$self; } 1;
ãã®ã¯ã©ã¹ã§ä»¥ä¸ã®ãã¹ããéãã¾ãã
my $list = List::RubyLike->new; isa_ok $list, 'List::RubyLike'; is $list->size, 0;
ãã®ã¯ã©ã¹ã«ä»ãå ããå½¢ã§ããªã¹ãã«å¯¾ããåºæ¬æä½ã§ãã push() 㨠join() ãå®è£ ãã¾ãã
package List::RubyLike; use strict; use warnings; use Params::Validate qw/:all/; sub new { my ($self, @list) = @_; my $class = ref $self || $self; bless \@list, $class; } sub size { my $self = shift; scalar @$self; } sub push { my ($self, @list) = @_; CORE::push @$self, @list; $self; } sub join { my ($self, $delimiter) = validate_pos(@_, 1, { type => SCALAR }); join $delimiter, @$self; } 1;
push ã $self ãè¿å´ãã¦ããã®ã§ãpush ã®è¿ãå¤ã«ã¯ç¶ã㦠List::RubyLike ã®ã¡ã½ãããå¼ã³åºããã¨ãã§ãã¾ãã
ããã§ä»¥ä¸ã®ãã¹ããéãã¾ããpush ã㦠join ã¨å¼ã³åºããç¹ãã£ã¦ããã¨ããã«æ³¨ç®ãã¦ãã ããã
$list->push(1, 2); is $list->size, 2; is $list->push(3)->join(','), '1,2,3';
åæ§ã«ã¡ã½ããã追å ãã¦ãããã¨ã§æ§ã ãªãªã¹ãæä½ãå¯è½ã«ãªãã§ããããä¾ãã°
is $list->push(3)->collect(sub { $_ * $_ })->reduce(sub { $_[0] + $_[1] }), 14;
ã¨ããããã«ããªã¹ãã®åè¦ç´ ã®èªä¹ã collect (map) ã§éãã¦ãrecduce() ã§ãã®åè¨ã¨ãããã¨ãããããªå¼ãã¯ã³ã©ã¤ãã¼ã§è¨è¿°ã§ããããã«ãããã¨ããã§ããå¿ è¦ãªã¡ã½ããã追å ãã¦ããã¾ããããã«
my $list = list(1, 2)
ã¨ããªã¹ãã®ä½æã List::RubyLike->new ã§ã¯ãªã list() ã¨æ軽ã«è¡ããããã«ãã¾ããå®è£ ã¯ä»¥ä¸ã®ããã«ãªãã¾ãã
package List::RubyLike; use strict; use warnings; use Params::Validate qw/:all/; use Exporter::Lite; use List::Util (); our @EXPORT = qw/list/; sub list (@) { __PACKAGE__->new(@_); } sub new { my ($self, @list) = @_; my $class = ref $self || $self; bless \@list, $class; } sub size { my $self = shift; scalar @$self; } sub push { my ($self, @list) = @_; CORE::push @$self, @list; $self; } sub to_a { my $self = shift; [ $self->unblessed ]; } sub join { my ($self, $delimiter) = validate_pos(@_, 1, { type => SCALAR }); join $delimiter, @$self; } sub unblessed { my $self = shift; return @$self; } sub dup { my $self = shift; $self->new( $self->unblessed ); } sub collect { my ($self, $code) = validate_pos(@_, 1, { type => CODEREF }); my @collected = CORE::map &$code, @{$self->dup}; wantarray ? @collected : $self->new(@collected); } *map = \&collect; sub reduce { my ($self, $code) = validate_pos(@_, 1, { type => CODEREF }); List::Util::reduce sub { $code->($a, $b) }, @{$self->dup}; } 1;
ã ãã¶å¢ãã¦ãã¾ããããã®èª¿åã§ãªã¹ãæä½ã«å¿ è¦ãªã¡ã½ãããã©ãã©ãå ãã¦ããã°ããã Ruby ã®ãªã¹ãæä½ã¨åçã®æä½ãã¹ã¦ãç¶²ç¾ ããã®ãé£ããã¯ãªãã§ãããã
æ¼ç®å overload ã使ãã°
$list <<= 4; # push(@$list, 4)
ã¨ãã£ãã¤ã³ã¿ãã§ã¼ã¹ã追å ãããã¨ãå¯è½ã§ãã
CPAN ã«ã¯ List::Object ã List::oo ãªã©ããªã¹ãããªãã¸ã§ã¯ãæåçã«æ±ããããã«ããã¢ã¸ã¥ã¼ã«ãããã¤ãããããã§ãããã ãããããã Ruby ã»ã©è±å¯ãªæä½ãæä¾ããããã§ã¯ãªãããã§ããautobox ãå©ç¨ãã¦ä¼¼ããããªãã¨ããããã¨ãå¯è½ã§ãã
DBIx::MoCo ã®ãªã¹ãæä½
ãã®é¡ã®ãªã¹ãã¯ã©ã¹ãããã¨ä½ãè¯ãããã§ãããã©ããªããã°ã©ã ã§ãããã®å¤§é¨åã®å¦çã¯ãªã¹ãæä½ã§ããããå©ç¹ã¯èªæã§ãã
ä¾ãã° O/R ãããã® DBIx::MoCo ã¯ãDB ã«åãåããã¦è¿å´ãããã¬ã³ã¼ããªãã¸ã§ã¯ãããä¸è¨ã®ãããªãªã¹ãã¯ã©ã¹ã¨ãã¦è¿å´ãã¾ããå¾ã£ã¦
my $url = 'http://d.hatena.ne.jp/naoya/'; moco('Entry')->search(where => ["url like ? and count >= ?", "$url%", 5]) ->collect(sub { $_->url })->join("\n");
ã¨ããããã« search 㧠SQL ãçºè¡ããçµæã«å¯¾ãããªã¹ãæä½ãé£ç¶ãã¦å¼ã³åºããªãããã¼ã¿æ§é ãæä½ãããã¨ãã§ãã¾ãã
ç¾å¨éçºä¸ã®æ°ããã¯ã¦ãªããã¯ãã¼ã¯ã¯ããã¼ã¿ã½ã¼ã¹å±¤ã®ã©ã¤ãã©ãªã« DBIx::MoCo ã使ã£ã¦ãã¾ããã¯ã¦ãªããã¯ãã¼ã¯ã®ãã¼ã¿ãã¼ã¹ãæä½ããããç¹å®ã® URL ã«ä»ããããã¯ãã¼ã¯ä¸è¦§ãããã¦ã¼ã¶ã¼ã®ã¢ã¤ã³ã³ãªã¹ããåå¾ãã¦åºåãã¦ã¿ã¾ãã以ä¸ã®ããã«ã¯ã³ã©ã¤ãã¼ã§æ¸ãã¾ãã
use Hatena::Bookmark::MoCo qw/moco/; my $url = shift; print moco('Entry')->retrieve_by_url($url) ->bookmarks ->grep(sub { $_->user->is_public }) ->collect(sub { $_->user->profile->image->tag(32) }) ->join("\n");
ãã®ã³ã¼ãã http://d.hatena.ne.jp/naoya/20080415/1208225082 ã«å¯¾ãã¦å®è¡ããã¨ãçµæã¯ä»¥ä¸ã®ããã«ãªãã¾ãã
DBIx::MoCo ã«ã¯ Ruby ã©ã¤ã¯ãªãªã¹ãæä½æ©è½ä»¥å¤ã«ãmemcached ãå©ç¨ããééçãªãã£ãã·ã¥ã®æ©è½ããRails ã® ActiveRecord ã®ãããªæè»ãª SQL ã®çµã¿ç«ã¦ã¤ã³ã¿ãã§ã¼ã¹ããã¹ãã容æã«ããããã® fixture æ©è½ãªã©ãæè¼ããã¦ãã¾ããYAPC::Asia 2008 ã§ããå°ã詳ããç´¹ä»ãããã¨æã£ã¦ãã¾ãã