eab6729f795b9a2e131cfde5b2a72252ea8e86dc
[catagits/DOM-Tiny.git] / lib / DOM / Tiny / _Collection.pm
1 package DOM::Tiny::_Collection;
2
3 use strict;
4 use warnings;
5 use Carp 'croak';
6 use List::Util;
7 use Scalar::Util 'blessed';
8
9 our $VERSION = '0.002';
10
11 sub new {
12   my $class = shift;
13   return bless [@_], ref $class || $class;
14 }
15
16 sub TO_JSON { [@{shift()}] }
17
18 sub compact {
19   my $self = shift;
20   return $self->new(grep { defined && (ref || length) } @$self);
21 }
22
23 sub each {
24   my ($self, $cb) = @_;
25   return @$self unless $cb;
26   my $i = 1;
27   $_->$cb($i++) for @$self;
28   return $self;
29 }
30
31 sub first {
32   my ($self, $cb) = (shift, shift);
33   return $self->[0] unless $cb;
34   return List::Util::first { $_ =~ $cb } @$self if ref $cb eq 'Regexp';
35   return List::Util::first { $_->$cb(@_) } @$self;
36 }
37
38 sub flatten { $_[0]->new(_flatten(@{$_[0]})) }
39
40 sub grep {
41   my ($self, $cb) = (shift, shift);
42   return $self->new(grep { $_ =~ $cb } @$self) if ref $cb eq 'Regexp';
43   return $self->new(grep { $_->$cb(@_) } @$self);
44 }
45
46 sub join {
47   join $_[1] // '', map {"$_"} @{$_[0]};
48 }
49
50 sub last { shift->[-1] }
51
52 sub map {
53   my ($self, $cb) = (shift, shift);
54   return $self->new(map { $_->$cb(@_) } @$self);
55 }
56
57 sub reduce {
58   my $self = shift;
59   @_ = (@_, @$self);
60   goto &List::Util::reduce;
61 }
62
63 sub reverse { $_[0]->new(reverse @{$_[0]}) }
64
65 sub shuffle { $_[0]->new(List::Util::shuffle @{$_[0]}) }
66
67 sub size { scalar @{$_[0]} }
68
69 sub slice {
70   my $self = shift;
71   return $self->new(@$self[@_]);
72 }
73
74 sub sort {
75   my ($self, $cb) = @_;
76
77   return $self->new(sort @$self) unless $cb;
78
79   my $caller = caller;
80   no strict 'refs';
81   my @sorted = sort {
82     local (*{"${caller}::a"}, *{"${caller}::b"}) = (\$a, \$b);
83     $a->$cb($b);
84   } @$self;
85   return $self->new(@sorted);
86 }
87
88 sub tap {
89   my ($self, $cb) = (shift, shift);
90   $_->$cb(@_) for $self;
91   return $self;
92 }
93
94 sub to_array { [@{shift()}] }
95
96 sub uniq {
97   my ($self, $cb) = (shift, shift);
98   my %seen;
99   return $self->new(grep { !$seen{$_->$cb(@_)}++ } @$self) if $cb;
100   return $self->new(grep { !$seen{$_}++ } @$self);
101 }
102
103 sub _flatten {
104   map { _ref($_) ? _flatten(@$_) : $_ } @_;
105 }
106
107 sub _ref { ref $_[0] eq 'ARRAY' || blessed $_[0] && $_[0]->isa(__PACKAGE__) }
108
109 1;
110
111 =for Pod::Coverage *EVERYTHING*
112
113 =cut