List::Rubyish - Array iterator like the Ruby


List-Rubyish documentation Contained in the List-Rubyish distribution.

Index


Code Index:

NAME

Top

List::Rubyish - Array iterator like the Ruby

SYNOPSIS

Top

  my $array_ref = [
    {name => 'jkondo'},
    {name => 'cinnamon'}
  ];
  my $list = List::Rubyish->new($array_ref);

  $list->size;              #=> 2
  my $first = $list->shift; #=> {name => 'jkondo'}
  $list->push($first);      #=> [{name => 'cinnamon'}, {name => 'jkondo'}];

  # List::Rubyish provides much more useful methods. For more
  # details, see the sections below.

OVERVIEW

Top

DBIx::MoCo::List is very useful, However installation is complex.

List::Rubyish was made in order to enable use of DBIx::MoCo::List independently.

METHODS

Top

dump ()

Dump the content of $self using Data::Dumper.

push ( @array )
unshift ( @array )

Sets the argument into $self, a refernce to an array blessed by List::Rubyish, like the same name functions provided by Perl core, then returns a List::Rubyish object.

  my $list = List::Rubyish->new([qw(1 2 3)]);
  $list->push(4, 5); #=> [1, 2, 3, 4, 5]
  $list->unshift(0); #=> [0, 1, 2, 3, 4, 5]

concat ( \@array )
prepend ( \@array )

They're almost the same as push()/unshift() described above except that the argument shoud be a reference to an array.

  my $list = List::Rubyish->new([1, 2, 3]);
  $list->concat([4, 5]); #=> [1, 2, 3, 4, 5]
  $list->prepend([0]);   #=> [0, 1, 2, 3, 4, 5]

shift ()
pop ()

Pulls out the first/last element from $self, a refernce to an array blessed by List::Rubyish, then returns it like the same name functions in Perl core.

  $list = List::Rubyish->new([1, 2, 3]);
  $list->shift; #=> 1
  $list->pop;   #=> 3
  $list->dump   #=> [2]

first ()
last ()

Returns the first/last element of $self, a refernce to an array blessed by List::Rubyish. These methods aren't destructive contrary to shift()/pop() method.

  $list = List::Rubyish->new([1, 2, 3]);
  $list->first; #=> 1
  $list->last;  #=> 3
  $list->dump   #=> [1, 2, 3]

slice ( $start, $end )

Returns the elements whose indexes are between $start and $end as a List::Rubyish object.

  $list = List::Rubyish->new([qw(1 2 3 4)]);
  $list->slice(1, 2) #=> [2, 3]

zip ( \@array1, \@array2, ... )

Bundles up the elements in each arguments into an array or a List::Rubyish object along with the context.

  my $list = List::Rubyish->new([1, 2, 3]);
  $list->zip([4, 5, 6], [7, 8, 9]);
      #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

  # When the numbers of each list are different...
  $list = List::Rubyish->new([1, 2, 3]);
  $list->zip([4, 5], [7, 8, 9]);
      #=> [[1, 4, 7], [2, 5, 8], [3, undef, 9]]

  my $list   = List::Rubyish->new([1, 2]);
  $list->zip([4, 5], [7, 8, 9]);
      #=> [[1, 4, 7], [2, 5, 8]]

delete ( $value, $code )

Deletes the same values as $value in $self, a refernce to an array blessed by List::Rubyish, and returns the value if found. If the value is not found in $self and $code is passed in, the code is executed using the value as an argument to find the value to be deleted.

  $list = List::Rubyish->new([1, 2, 3, 2, 1]);
  $list->delete(2); #=> 2
  $list->dump       #=> [1, 3, 1]

delete_at ( $pos )

Deletes the element at $pos and returns it.

  $list = List::Rubyish->new([1, 2, 3, 2, 1]);
  $list->delete_at(3); #=> 2
  $list->dump          #=> [1, 2, 3, 1]

delete_if ( $code )

Deletes the elements if $code returns true value with each element as an argument.

  $list = List::Rubyish->new([1, 2, 3, 4]);
  $list->delete_if(sub { ($_ % 2) == 0) });
  $list->dump #=> [1, 3]

inject ( $result, $code )

Executes folding calculation using $code through each element and returns the result.

  $list = List::Rubyish->new([1, 2, 3, 4]);
  $list->inject(0, sub { $_[0] + $_[1] }); #=> 10

join ( $delimiter )

Joins all the elements by $delimiter.

  $list = List::Rubyish->new([0 1 2 3]);
  $list->join(', ') #=> '0, 1, 2, 3'

each_index ( $code )

Executes $code with each index of $self, a refernce to an array blessed by List::Rubyish.

  $list = List::Rubyish->new([1, 2, 3]);
  $list->each_index(sub { do_something($_) });

each ( $code )

Executes $code with each value of $self, a refernce to an array blessed by List::Rubyish.

  $list = List::Rubyish->new([1, 2, 3]);
  $list->each(sub { do_something($_) });

collect ( $code )

Executes $code with each element of $self, a refernce to an array blessed by List::Rubyish using CORE::map() and returns the results as a list or List::Rubyish object along with the context.

  $list = List::Rubyish->new([1, 2, 3]);
  $list->map(sub { $_ * 2 }); #=> [2, 4, 6]

map ( $code )

An alias of collect() method described above.

grep ( $code )

Executes $code with each element of $self, a refernce to an array blessed by List::Rubyish using CORE::grep() and returns the results as a list or List::Rubyish object along with the context.

  $list = List::Rubyish->new([qw(1 2 3 4)]);
  $list->grep(sub { ($_ % 2) == 0 }); #=> [2, 4]

find ( $code )

Returns the first value found in $self, a refernce to an array blessed by List::Rubyish, as a result of $code..

  $list = List::Rubyish->new([1, 2, 3, 4]);
  $list->find(sub { ($_ % 2) == 0 }); #=> 2

select ( $code )

Returns the values found in $self, a refernce to an array blessed by List::Rubyish, as a result of $code..

  $list = List::Rubyish->new([1, 2, 3, 4]);
  $list->select(sub { ($_ % 2) == 0 }); #=> 2, 4

index_of ( $arg )

Returns index of given target or given code returns true.

  $list = List::Rubyish->new([qw(foo bar baz)]);
  $list->index_of('bar');                  #=> 1
  $list->index_of(sub { shift eq 'bar' }); #=> 1

sort ( $code )

Sorts out each element and returns the result as a list or List::Rubyish object along with the context.

  $list = List::Rubyish->new([qw(3 2 4 1]);
  $list->sort;                          #=> [1, 2, 3, 4]
  $list->sort(sub { $_[1] <=> $_[0] }); #=> [4, 3, 2, 1]

sort_by ( $code, $cmp )

Sorts out each element with Schwartzian transform returns the result as a list or List::Rubyish object along with the context.

  $list = List::Rubyish->new([ [3], [2], [4], [1]]);
  $list->sort_by(sub { $_->[0] }); #=> [[1], [2], [3], [4]]
  $list->sort_by(sub { $_->[0] }, sub { $_[1} <=> $_[0] } ); #=> [[4], [3], [2], [1]]

compact ()

Eliminates undefined values in $self, a refernce to an array blessed by List::Rubyish.

  $list = List::Rubyish->new([1, 2, undef, 3, undef, 4]);
  $list->compact; #=> [1, 2, 3, 4]

length ()

Returns the length of $self, a refernce to an array blessed by List::Rubyish.

  $list = List::Rubyish->new([qw(1 2 3 4)]);
  $list->length; #=> 4

size ()

An alias of length() method described above.

flatten ()

Returns a list or List::Rubyish object which is recursively flattened out.

  $list = List::Rubyish->new([1, [2, 3, [4], 5]]);
  $list->flattern; #=> [1, 2, 3, 4, 5]

is_empty ()

Returns true if $self, a refernce to an array blessed by List::Rubyish, is empty.

uniq ()

Uniquifies the elements in $self, a refernce to an array blessed by List::Rubyish, and returns the result.

  $list = List::Rubyish->new([1, 2, 2, 3, 3, 4])
  $list->uniq; #=> [1, 2, 3, 4]

reduce ( $code )

Reduces the list by $code.

  # finds the maximum value
  $list = List::Rubyish->new([4, 1, 3, 2])
  $list->reduce(sub { $_[0] > $_[1] ? $_[0] : $_[1] }); #=> 4

See List::Util to get to know about details of reduce().

reverse ()

Returns an reversely ordered $self, a refernce to an array blessed by List::Rubyish.

  $list = List::Rubyish->new([4, 1, 3, 2])
  $list->reverse; #=> [2, 3, 1, 4]

dup ()

Returns a duplicated $self, a refernce to an array blessed by List::Rubyish.

sum ()

Returns the sum of each element in $self, a refernce to an array blessed by List::Rubyish.

  $list = List::Rubyish->new([1, 2, 3, 4]);
  $list->sum; #=> 10

SEE ALSO

Top

DBIx::MoCo::List, List::Util, List::MoreUtils, http://github.com/naoya/list-rubylike, http://d.hatena.ne.jp/naoya/20080419/1208579525, http://www.ruby-lang.org/ja/man/html/Enumerable.html

AUTHOR

Top

Junya Kondo, <jkondo@hatena.com>, Naoya Ito, <naoya@hatena.ne.jp>, Kentaro Kuribayashi, <kentarok@gmail.com>, Yuichi Tateno, <secondlife at hatena ne jp<gt>,

Kazuhiro Osawa <yappo <at> shibuya <döt> pl>

thanks to

naoya, kentaro, tokuhirom, kan, lopnor

REPOSITORY

Top

  svn co http://svn.coderepos.org/share/lang/perl/List-Rubyish/trunk List-Rubyish

List::Rubyish is Subversion repository is hosted at http://coderepos.org/share/. patches and collaborators are welcome.

LICENSE

Top

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

DBIx::MoCo::List's COPYRIGHT

Top


List-Rubyish documentation Contained in the List-Rubyish distribution.

package List::Rubyish;
use strict;
use warnings;
use 5.008001;
use overload
    '<<'     => sub {
        my($self, $add) = @_;
        $add = [ $add ] unless ref($add) eq 'ARRAY' || ref($add) eq ref($self);
        $self->push(@$add);
    },
    '>>'     => sub {
        my($self, $add) = @_;
        if (ref($self) eq ref($add)) {
            my $tmp = $self; $self = $add; $add = $tmp;
        } elsif (ref($add) ne 'ARRAY') {
            $add = [ $add ];
        }
        $self->unshift(@$add);
    },
    '+'      => sub {
        my($self, $add, $flag) = @_;
        $add = [ $add ] unless ref($add) eq 'ARRAY' || ref($add) eq ref($self);
        $self->add($add, $flag);
    },
    fallback => 1;

our $VERSION = '0.03';

use Carp qw/croak/;
use List::Util ();
use List::MoreUtils ();

sub new {
    my $class = shift;
    $class = ref $class if ref $class;
    my $array =  @_ > 0 ? (@_ == 1 && ref($_[0]) eq 'ARRAY') ? shift : [ @_ ] : [];
    bless $array, $class;
}

sub push {
    my $self = shift;
    push @$self, @_;
    $self;
}

sub unshift {
    my $self = shift;
    unshift @$self, @_;
    $self;
}

sub shift {
    shift @{$_[0]};
}

sub pop {
    pop @{$_[0]};
}

sub first {
    my ($self, $num) = @_;
    if (defined $num) {
        return $self->slice(0, $num - 1);
    } else {
        return $self->[0];
    }
}

sub last {
    my ($self, $num) = @_;
    if (defined $num) {
        return $self->slice($self->_last_index - $num + 1, $self->_last_index);
    } else {
        return $self->[-1];
    }
}

sub slice {
    my $self = CORE::shift;
    my ($start, $end) = @_;
    my $last = $#{$self};
    if (defined $end) {
        if ($start == 0 && $last <= $end) {
            return $self;
        } else {
            $end = $last if $last < $end;
            return $self->new([ @$self[ $start .. $end ] ]);
        }
    } elsif (defined $start && 0 < $start && $last <= $start) {
        return $self->new([]);
    } else {
        return $self;
    }
}

sub dump {
    my $self = CORE::shift;
    require Data::Dumper;
    Data::Dumper->new([ $self->to_a ])->Purity(1)->Terse(1)->Dump;
}

sub zip {
    my $self = CORE::shift;
    my $array = \@_;
    my $index = 0;
    $self->collect(sub { 
         my $ary = $self->new([$_]);
         $ary->push($_->[$index]) for @$array;
         $index++;
         $ary;
    });
}

sub delete {
    my ($self, $value, $code) = @_;
    my $found = 0;
    if (ref $value eq 'CODE') {
        do { my $item = $self->shift; $value->($item) ? $found = 1 : $self->push($item) } for (0..$self->_last_index);
    } else {
        do { my $item = $self->shift; $item eq $value ? $found = 1 : $self->push($item) } for (0..$self->_last_index);
    }
    $found ? $value 
           : ref $code eq 'CODE' ? do { local $_ = $value; return $code->($_) }
                                 : return ;
}

sub delete_at {
    my ($self, $pos) = @_;
    my $last_index = $self->_last_index;
    return if $pos > $last_index ;
    my $result;
    $_ == $pos ? $result = $self->shift 
               : $self->push($self->shift) for 0..$last_index;
    return $result;
}

sub delete_if {
    my ($self, $code) = @_;
    croak "Argument must be a code" unless ref $code eq 'CODE';
    my $last_index = $self->_last_index;
    for (0..$last_index) {
        my $item = $self->shift;
        local $_ = $item;
        $self->push($item) unless $code->($_);
    }
    return $self;
}

sub reject {
    my ($self, $code) = @_;
    return $self->dup->delete_if($code);
}

sub inject {
    my ($self, $result, $code) = @_;
    croak "Argument must be a code" unless ref $code eq 'CODE';
    $result = $code->($result, $_) for @{$self->dup};
    return $result;
}

sub join {
    my ($self, $delimiter) = @_;
    join $delimiter, @$self;
}

sub each_index {
    my ($self, $code) = @_;
    $self->new([ 0..$self->_last_index ])->each($code);
}

sub _last_index {
    my $self = CORE::shift;
    $self->length ? $self->length - 1 : 0;
};

sub concat {
    my ($self, $array) = @_;
    $self->push(@$array);
    $self;
}

*append = \&concat;

sub prepend {
    my ($self, $array) = @_;
    $self->unshift(@$array);
    $self;
}

sub _append_undestructive {
    my ($self, $array) = @_;
    $self->dup->push(@$array);
}

sub _prepend_undestructive {
    my ($self, $array) = @_;
    $self->dup->unshift(@$array);
}

sub add {
    my ($self, $array, $bool) = @_;
    $bool ? $self->_prepend_undestructive($array)
          : $self->_append_undestructive($array);
}

sub each {
    my ($self, $code) = @_;
    croak "Argument must be a code" unless ref $code eq 'CODE';
    $code->($_) for @{$self->dup};
    $self;
}

sub collect {
    my ($self, $code) = @_;
    croak "Argument must be a code" unless ref $code eq 'CODE';
    my @collected = CORE::map &$code, @{$self->dup};
    wantarray ? @collected : $self->new(\@collected);
}

*map = \&collect;

sub grep {
    my ($self, $code) = @_;
    $code or return;
    my @grepped;
    if (!ref($code)) {
        for (@$self) {
            if (ref($_) eq 'HASH') {
                CORE::push @grepped, $_ if $_->{$code};
            } else {
                CORE::push @grepped, $_ if $_->$code;
            }
        }
    } elsif (ref $code eq 'CODE') {
        @grepped = CORE::grep &$code, @$self;
    } else {
        croak "Invalid code";
    }
    wantarray ? @grepped : $self->new(\@grepped);
}

sub find {
    my ($self, $cond) = @_;
    my $code = (ref $cond and ref $cond eq 'CODE')
        ? $cond
        : sub { $_ eq $cond };

    for (@$self) { &$code and return $_ }
    return;
}

*detect = \&find;

sub select {
    my ($self, $code) = @_;
    croak "Argument must be a code" unless ref $code eq 'CODE';
    return $self unless $self->size;
    my $last_index = $self->_last_index;
    my $new = $self->dup;
    for (0..$last_index) {
        my $item = $new->shift;
        local $_ = $item;
        $new->push($item) if $code->($_);
    }
    return $new;
}

*find_all = \&select;

sub index_of {
    my ($self, $target) = @_;
    my $code = (ref $target eq 'CODE') ? $target : sub { CORE::shift eq $target };

    for (my $i = 0; $i < $self->length; $i++) {
        $code->($self->[$i]) and return $i;
    }
    return;
}

sub sort {
    my ($self, $code) = @_;
    my @sorted = $code ? CORE::sort { $code->($a, $b) } @$self : CORE::sort @$self;
    wantarray ? @sorted : $self->new(\@sorted);
}

sub sort_by {
    my ($self, $code, $cmp) = @_;

    my @sorted = $cmp ?
        CORE::map { $_->[1] } CORE::sort { $cmp->($a->[0], $b->[0]) } CORE::map { [$code->($_), $_] } @$self :
        CORE::map { $_->[1] } CORE::sort { $a->[0] <=> $b->[0] } CORE::map { [$code->($_), $_] } @$self;

    wantarray ? @sorted : $self->new(\@sorted);
}

sub compact {
    CORE::shift->grep(sub { defined  });
}

sub length {
    scalar @{$_[0]};
}

*size = \&length;

sub flatten {
    my $self = CORE::shift;
    $self->collect(sub { _flatten($_)  });
}

sub _flatten {
    my $element = CORE::shift;
    (ref $element and ref $element eq 'ARRAY')
        ? CORE::map { _flatten($_) } @$element
        : $element;
}

sub is_empty {
    !$_[0]->length;
}

sub uniq {
    my $self = CORE::shift;
    $self->new([ List::MoreUtils::uniq(@$self) ]);
}

sub reduce {
    my ($self, $code) = @_;
    croak "Argument must be a code" unless ref $code eq 'CODE';
    List::Util::reduce { $code->($a, $b) } @$self;
}

sub to_a {
    my @unblessed = @{$_[0]};
    \@unblessed;
}

sub as_list { # for Template::Iterator
    CORE::shift;
}

sub dup {
    __PACKAGE__->new($_[0]->to_a);
}

sub reverse {
    my $self = CORE::shift;
    $self->new([ reverse @$self ]);
}

sub sum {
    List::Util::sum @{$_[0]};
}

1;

__END__