From: Dan Book Date: Mon, 9 Nov 2015 05:27:12 +0000 (-0500) Subject: move collection documentation to main module X-Git-Tag: v0.001~11 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=78ba405129a79256aac6d3d2d95a2758630bda0f;hp=54805c33c9a398b644923d7184778edc542ecfd7;p=catagits%2FDOM-Tiny.git move collection documentation to main module --- diff --git a/META.json b/META.json index d523916..2c6a671 100644 --- a/META.json +++ b/META.json @@ -62,10 +62,6 @@ "file" : "lib/DOM/Tiny/CSS.pm", "version" : "0.001" }, - "DOM::Tiny::Collection" : { - "file" : "lib/DOM/Tiny/Collection.pm", - "version" : "0.001" - }, "DOM::Tiny::Entities" : { "file" : "lib/DOM/Tiny/Entities.pm", "version" : "0.001" diff --git a/README.pod b/README.pod index 3c86b61..01d617a 100644 --- a/README.pod +++ b/README.pod @@ -2,6 +2,8 @@ =encoding utf8 +=for Pod::Coverage TO_JSON + =head1 NAME DOM::Tiny - Minimalistic HTML/XML DOM parser with CSS selectors @@ -675,6 +677,217 @@ Alias for L. Alias for L. +=head1 COLLECTION METHODS + +Some L methods return an array-based collection object, which can +either be accessed directly as an array reference, or with the following +methods. + + # Chain methods + $collection->map(sub { ucfirst })->shuffle->each(sub { + my ($word, $num) = @_; + say "$num: $word"; + }); + + # Access array directly to manipulate collection + $collection->[23] += 100; + say for @$collection; + +=head2 compact + + my $new = $collection->compact; + +Create a new collection with all elements that are defined and not an empty +string. + + # $collection contains (0, 1, undef, 2, '', 3) + $collection->compact->join(', '); # "0, 1, 2, 3" + +=head2 each + + my @elements = $collection->each; + $collection = $collection->each(sub {...}); + +Evaluate callback for each element in collection or return all elements as a +list if none has been provided. The element will be the first argument passed +to the callback and is also available as C<$_>. + + # Make a numbered list + $collection->each(sub { + my ($e, $num) = @_; + say "$num: $e"; + }); + +=head2 first + + my $first = $collection->first; + my $first = $collection->first(qr/foo/); + my $first = $collection->first(sub {...}); + my $first = $collection->first($method); + my $first = $collection->first($method, @args); + +Evaluate regular expression/callback for, or call method on, each element in +collection and return the first one that matched the regular expression, or for +which the callback/method returned true. The element will be the first argument +passed to the callback and is also available as C<$_>. + + # Longer version + my $first = $collection->first(sub { $_->$method(@args) }); + + # Find first value that contains the word "dom" + my $interesting = $collection->first(qr/dom/i); + + # Find first value that is greater than 5 + my $greater = $collection->first(sub { $_ > 5 }); + +=head2 flatten + + my $new = $collection->flatten; + +Flatten nested collections/arrays recursively and create a new collection with +all elements. + + # $collection contains (1, [2, [3, 4], 5, [6]], 7) + $collection->flatten->join(', '); # "1, 2, 3, 4, 5, 6, 7" + +=head2 grep + + my $new = $collection->grep(qr/foo/); + my $new = $collection->grep(sub {...}); + my $new = $collection->grep($method); + my $new = $collection->grep($method, @args); + +Evaluate regular expression/callback for, or call method on, each element in +collection and create a new collection with all elements that matched the +regular expression, or for which the callback/method returned true. The element +will be the first argument passed to the callback and is also available as +C<$_>. + + # Longer version + my $new = $collection->grep(sub { $_->$method(@args) }); + + # Find all values that contain the word "dom" + my $interesting = $collection->grep(qr/dom/i); + + # Find all values that are greater than 5 + my $greater = $collection->grep(sub { $_ > 5 }); + +=head2 join + + my $stream = $collection->join; + my $stream = $collection->join("\n"); + +Turn collection into string. + + # Join all values with commas + $collection->join(', '); + +=head2 last + + my $last = $collection->last; + +Return the last element in collection. + +=head2 map + + my $new = $collection->map(sub {...}); + my $new = $collection->map($method); + my $new = $collection->map($method, @args); + +Evaluate callback for, or call method on, each element in collection and create +a new collection from the results. The element will be the first argument +passed to the callback and is also available as C<$_>. + + # Longer version + my $new = $collection->map(sub { $_->$method(@args) }); + + # Append the word "dom" to all values + my $domified = $collection->map(sub { $_ . 'dom' }); + +=head2 reduce + + my $result = $collection->reduce(sub {...}); + my $result = $collection->reduce(sub {...}, $initial); + +Reduce elements in collection with callback, the first element will be used as +initial value if none has been provided. + + # Calculate the sum of all values + my $sum = $collection->reduce(sub { $a + $b }); + + # Count how often each value occurs in collection + my $hash = $collection->reduce(sub { $a->{$b}++; $a }, {}); + +=head2 reverse + + my $new = $collection->reverse; + +Create a new collection with all elements in reverse order. + +=head2 slice + + my $new = $collection->slice(4 .. 7); + +Create a new collection with all selected elements. + + # $collection contains ('A', 'B', 'C', 'D', 'E') + $collection->slice(1, 2, 4)->join(' '); # "B C E" + +=head2 shuffle + + my $new = $collection->shuffle; + +Create a new collection with all elements in random order. + +=head2 size + + my $size = $collection->size; + +Number of elements in collection. + +=head2 sort + + my $new = $collection->sort; + my $new = $collection->sort(sub {...}); + +Sort elements based on return value of callback and create a new collection +from the results. + + # Sort values case-insensitive + my $case_insensitive = $collection->sort(sub { uc($a) cmp uc($b) }); + +=head2 tap + + $collection = $collection->tap(sub {...}); + +Equivalent to L. + +=head2 to_array + + my $array = $collection->to_array; + +Turn collection into array reference. + +=head2 uniq + + my $new = $collection->uniq; + my $new = $collection->uniq(sub {...}); + my $new = $collection->uniq($method); + my $new = $collection->uniq($method, @args); + +Create a new collection without duplicate elements, using the string +representation of either the elements or the return value of the +callback/method. + + # Longer version + my $new = $collection->uniq(sub { $_->$method(@args) }); + + # $collection contains ('foo', 'bar', 'bar', 'baz') + $collection->uniq->join(' '); # "foo bar baz" + + # $collection contains ([1, 2], [2, 1], [3, 2]) + $collection->uniq(sub{ $_->[1] })->to_array; # "[[1, 2], [2, 1]]" + =head1 BUGS Report any issues on the public bugtracker. diff --git a/lib/DOM/Tiny.pm b/lib/DOM/Tiny.pm index 699ffd9..bcaeb87 100644 --- a/lib/DOM/Tiny.pm +++ b/lib/DOM/Tiny.pm @@ -11,7 +11,7 @@ use overload fallback => 1; use Carp 'croak'; -use DOM::Tiny::Collection; +use DOM::Tiny::_Collection; use DOM::Tiny::CSS; use DOM::Tiny::HTML; use Scalar::Util qw(blessed weaken); @@ -24,6 +24,8 @@ sub new { return @_ ? $self->parse(@_) : $self; } +sub TO_JSON { shift->_delegate('render') } + sub all_text { shift->_all_text(1, @_) } sub ancestors { _select($_[0]->_collect($_[0]->_ancestors), $_[1]) } @@ -151,7 +153,7 @@ sub tag { return $self; } -sub tap { shift->DOM::Tiny::Collection::tap(@_) } +sub tap { shift->DOM::Tiny::_Collection::tap(@_) } sub text { shift->_all_text(0, @_) } @@ -223,7 +225,7 @@ sub _build { shift->new->tree(shift)->xml(shift) } sub _collect { my $self = shift; my $xml = $self->xml; - return DOM::Tiny::Collection->new(map { $self->_build($_, $xml) } @_); + return DOM::Tiny::_Collection->new(map { $self->_build($_, $xml) } @_); } sub _content { @@ -387,6 +389,8 @@ sub _wrap { =encoding utf8 +=for Pod::Coverage TO_JSON + =head1 NAME DOM::Tiny - Minimalistic HTML/XML DOM parser with CSS selectors @@ -1060,6 +1064,217 @@ Alias for L. Alias for L. +=head1 COLLECTION METHODS + +Some L methods return an array-based collection object, which can +either be accessed directly as an array reference, or with the following +methods. + + # Chain methods + $collection->map(sub { ucfirst })->shuffle->each(sub { + my ($word, $num) = @_; + say "$num: $word"; + }); + + # Access array directly to manipulate collection + $collection->[23] += 100; + say for @$collection; + +=head2 compact + + my $new = $collection->compact; + +Create a new collection with all elements that are defined and not an empty +string. + + # $collection contains (0, 1, undef, 2, '', 3) + $collection->compact->join(', '); # "0, 1, 2, 3" + +=head2 each + + my @elements = $collection->each; + $collection = $collection->each(sub {...}); + +Evaluate callback for each element in collection or return all elements as a +list if none has been provided. The element will be the first argument passed +to the callback and is also available as C<$_>. + + # Make a numbered list + $collection->each(sub { + my ($e, $num) = @_; + say "$num: $e"; + }); + +=head2 first + + my $first = $collection->first; + my $first = $collection->first(qr/foo/); + my $first = $collection->first(sub {...}); + my $first = $collection->first($method); + my $first = $collection->first($method, @args); + +Evaluate regular expression/callback for, or call method on, each element in +collection and return the first one that matched the regular expression, or for +which the callback/method returned true. The element will be the first argument +passed to the callback and is also available as C<$_>. + + # Longer version + my $first = $collection->first(sub { $_->$method(@args) }); + + # Find first value that contains the word "dom" + my $interesting = $collection->first(qr/dom/i); + + # Find first value that is greater than 5 + my $greater = $collection->first(sub { $_ > 5 }); + +=head2 flatten + + my $new = $collection->flatten; + +Flatten nested collections/arrays recursively and create a new collection with +all elements. + + # $collection contains (1, [2, [3, 4], 5, [6]], 7) + $collection->flatten->join(', '); # "1, 2, 3, 4, 5, 6, 7" + +=head2 grep + + my $new = $collection->grep(qr/foo/); + my $new = $collection->grep(sub {...}); + my $new = $collection->grep($method); + my $new = $collection->grep($method, @args); + +Evaluate regular expression/callback for, or call method on, each element in +collection and create a new collection with all elements that matched the +regular expression, or for which the callback/method returned true. The element +will be the first argument passed to the callback and is also available as +C<$_>. + + # Longer version + my $new = $collection->grep(sub { $_->$method(@args) }); + + # Find all values that contain the word "dom" + my $interesting = $collection->grep(qr/dom/i); + + # Find all values that are greater than 5 + my $greater = $collection->grep(sub { $_ > 5 }); + +=head2 join + + my $stream = $collection->join; + my $stream = $collection->join("\n"); + +Turn collection into string. + + # Join all values with commas + $collection->join(', '); + +=head2 last + + my $last = $collection->last; + +Return the last element in collection. + +=head2 map + + my $new = $collection->map(sub {...}); + my $new = $collection->map($method); + my $new = $collection->map($method, @args); + +Evaluate callback for, or call method on, each element in collection and create +a new collection from the results. The element will be the first argument +passed to the callback and is also available as C<$_>. + + # Longer version + my $new = $collection->map(sub { $_->$method(@args) }); + + # Append the word "dom" to all values + my $domified = $collection->map(sub { $_ . 'dom' }); + +=head2 reduce + + my $result = $collection->reduce(sub {...}); + my $result = $collection->reduce(sub {...}, $initial); + +Reduce elements in collection with callback, the first element will be used as +initial value if none has been provided. + + # Calculate the sum of all values + my $sum = $collection->reduce(sub { $a + $b }); + + # Count how often each value occurs in collection + my $hash = $collection->reduce(sub { $a->{$b}++; $a }, {}); + +=head2 reverse + + my $new = $collection->reverse; + +Create a new collection with all elements in reverse order. + +=head2 slice + + my $new = $collection->slice(4 .. 7); + +Create a new collection with all selected elements. + + # $collection contains ('A', 'B', 'C', 'D', 'E') + $collection->slice(1, 2, 4)->join(' '); # "B C E" + +=head2 shuffle + + my $new = $collection->shuffle; + +Create a new collection with all elements in random order. + +=head2 size + + my $size = $collection->size; + +Number of elements in collection. + +=head2 sort + + my $new = $collection->sort; + my $new = $collection->sort(sub {...}); + +Sort elements based on return value of callback and create a new collection +from the results. + + # Sort values case-insensitive + my $case_insensitive = $collection->sort(sub { uc($a) cmp uc($b) }); + +=head2 tap + + $collection = $collection->tap(sub {...}); + +Equivalent to L. + +=head2 to_array + + my $array = $collection->to_array; + +Turn collection into array reference. + +=head2 uniq + + my $new = $collection->uniq; + my $new = $collection->uniq(sub {...}); + my $new = $collection->uniq($method); + my $new = $collection->uniq($method, @args); + +Create a new collection without duplicate elements, using the string +representation of either the elements or the return value of the +callback/method. + + # Longer version + my $new = $collection->uniq(sub { $_->$method(@args) }); + + # $collection contains ('foo', 'bar', 'bar', 'baz') + $collection->uniq->join(' '); # "foo bar baz" + + # $collection contains ([1, 2], [2, 1], [3, 2]) + $collection->uniq(sub{ $_->[1] })->to_array; # "[[1, 2], [2, 1]]" + =head1 BUGS Report any issues on the public bugtracker. diff --git a/lib/DOM/Tiny/Collection.pm b/lib/DOM/Tiny/Collection.pm deleted file mode 100644 index 0f678c2..0000000 --- a/lib/DOM/Tiny/Collection.pm +++ /dev/null @@ -1,371 +0,0 @@ -package DOM::Tiny::Collection; - -use strict; -use warnings; -use Carp 'croak'; -use List::Util; -use Scalar::Util 'blessed'; - -our $VERSION = '0.001'; - -sub new { - my $class = shift; - return bless [@_], ref $class || $class; -} - -sub TO_JSON { [@{shift()}] } - -sub compact { - my $self = shift; - return $self->new(grep { defined && (ref || length) } @$self); -} - -sub each { - my ($self, $cb) = @_; - return @$self unless $cb; - my $i = 1; - $_->$cb($i++) for @$self; - return $self; -} - -sub first { - my ($self, $cb) = (shift, shift); - return $self->[0] unless $cb; - return List::Util::first { $_ =~ $cb } @$self if ref $cb eq 'Regexp'; - return List::Util::first { $_->$cb(@_) } @$self; -} - -sub flatten { $_[0]->new(_flatten(@{$_[0]})) } - -sub grep { - my ($self, $cb) = (shift, shift); - return $self->new(grep { $_ =~ $cb } @$self) if ref $cb eq 'Regexp'; - return $self->new(grep { $_->$cb(@_) } @$self); -} - -sub join { - join $_[1] // '', map {"$_"} @{$_[0]}; -} - -sub last { shift->[-1] } - -sub map { - my ($self, $cb) = (shift, shift); - return $self->new(map { $_->$cb(@_) } @$self); -} - -sub reduce { - my $self = shift; - @_ = (@_, @$self); - goto &List::Util::reduce; -} - -sub reverse { $_[0]->new(reverse @{$_[0]}) } - -sub shuffle { $_[0]->new(List::Util::shuffle @{$_[0]}) } - -sub size { scalar @{$_[0]} } - -sub slice { - my $self = shift; - return $self->new(@$self[@_]); -} - -sub sort { - my ($self, $cb) = @_; - - return $self->new(sort @$self) unless $cb; - - my $caller = caller; - no strict 'refs'; - my @sorted = sort { - local (*{"${caller}::a"}, *{"${caller}::b"}) = (\$a, \$b); - $a->$cb($b); - } @$self; - return $self->new(@sorted); -} - -sub tap { - my ($self, $cb) = (shift, shift); - $_->$cb(@_) for $self; - return $self; -} - -sub to_array { [@{shift()}] } - -sub uniq { - my ($self, $cb) = (shift, shift); - my %seen; - return $self->new(grep { !$seen{$_->$cb(@_)}++ } @$self) if $cb; - return $self->new(grep { !$seen{$_}++ } @$self); -} - -sub _flatten { - map { _ref($_) ? _flatten(@$_) : $_ } @_; -} - -sub _ref { ref $_[0] eq 'ARRAY' || blessed $_[0] && $_[0]->isa(__PACKAGE__) } - -1; - -=encoding utf8 - -=head1 NAME - -DOM::Tiny::Collection - Collection - -=head1 SYNOPSIS - - use DOM::Tiny::Collection; - - # Manipulate collection - my $collection = DOM::Tiny::Collection->new(qw(just works)); - unshift @$collection, 'it'; - say $collection->join("\n"); - - # Chain methods - $collection->map(sub { ucfirst })->shuffle->each(sub { - my ($word, $num) = @_; - say "$num: $word"; - }); - -=head1 DESCRIPTION - -L is an array-based container for collections of -L nodes or other items based on L. - - # Access array directly to manipulate collection - my $collection = DOM::Tiny::Collection->new(1 .. 25); - $collection->[23] += 100; - say for @$collection; - -=head1 METHODS - -L implements the following methods. - -=head2 new - - my $collection = DOM::Tiny::Collection->new(1, 2, 3); - -Construct a new array-based L object. - -=head2 TO_JSON - - my $array = $collection->TO_JSON; - -Alias for L. - -=head2 compact - - my $new = $collection->compact; - -Create a new collection with all elements that are defined and not an empty -string. - - # "0, 1, 2, 3" - DOM::Tiny::Collection->new(0, 1, undef, 2, '', 3)->compact->join(', '); - -=head2 each - - my @elements = $collection->each; - $collection = $collection->each(sub {...}); - -Evaluate callback for each element in collection or return all elements as a -list if none has been provided. The element will be the first argument passed -to the callback and is also available as C<$_>. - - # Make a numbered list - $collection->each(sub { - my ($e, $num) = @_; - say "$num: $e"; - }); - -=head2 first - - my $first = $collection->first; - my $first = $collection->first(qr/foo/); - my $first = $collection->first(sub {...}); - my $first = $collection->first($method); - my $first = $collection->first($method, @args); - -Evaluate regular expression/callback for, or call method on, each element in -collection and return the first one that matched the regular expression, or for -which the callback/method returned true. The element will be the first argument -passed to the callback and is also available as C<$_>. - - # Longer version - my $first = $collection->first(sub { $_->$method(@args) }); - - # Find first value that contains the word "dom" - my $interesting = $collection->first(qr/dom/i); - - # Find first value that is greater than 5 - my $greater = $collection->first(sub { $_ > 5 }); - -=head2 flatten - - my $new = $collection->flatten; - -Flatten nested collections/arrays recursively and create a new collection with -all elements. - - # "1, 2, 3, 4, 5, 6, 7" - DOM::Tiny::Collection->new(1, [2, [3, 4], 5, [6]], 7)->flatten->join(', '); - -=head2 grep - - my $new = $collection->grep(qr/foo/); - my $new = $collection->grep(sub {...}); - my $new = $collection->grep($method); - my $new = $collection->grep($method, @args); - -Evaluate regular expression/callback for, or call method on, each element in -collection and create a new collection with all elements that matched the -regular expression, or for which the callback/method returned true. The element -will be the first argument passed to the callback and is also available as -C<$_>. - - # Longer version - my $new = $collection->grep(sub { $_->$method(@args) }); - - # Find all values that contain the word "dom" - my $interesting = $collection->grep(qr/dom/i); - - # Find all values that are greater than 5 - my $greater = $collection->grep(sub { $_ > 5 }); - -=head2 join - - my $stream = $collection->join; - my $stream = $collection->join("\n"); - -Turn collection into string. - - # Join all values with commas - $collection->join(', ')->say; - -=head2 last - - my $last = $collection->last; - -Return the last element in collection. - -=head2 map - - my $new = $collection->map(sub {...}); - my $new = $collection->map($method); - my $new = $collection->map($method, @args); - -Evaluate callback for, or call method on, each element in collection and create -a new collection from the results. The element will be the first argument -passed to the callback and is also available as C<$_>. - - # Longer version - my $new = $collection->map(sub { $_->$method(@args) }); - - # Append the word "dom" to all values - my $domified = $collection->map(sub { $_ . 'dom' }); - -=head2 reduce - - my $result = $collection->reduce(sub {...}); - my $result = $collection->reduce(sub {...}, $initial); - -Reduce elements in collection with callback, the first element will be used as -initial value if none has been provided. - - # Calculate the sum of all values - my $sum = $collection->reduce(sub { $a + $b }); - - # Count how often each value occurs in collection - my $hash = $collection->reduce(sub { $a->{$b}++; $a }, {}); - -=head2 reverse - - my $new = $collection->reverse; - -Create a new collection with all elements in reverse order. - -=head2 slice - - my $new = $collection->slice(4 .. 7); - -Create a new collection with all selected elements. - - # "B C E" - DOM::Tiny::Collection->new('A', 'B', 'C', 'D', 'E')->slice(1, 2, 4)->join(' '); - -=head2 shuffle - - my $new = $collection->shuffle; - -Create a new collection with all elements in random order. - -=head2 size - - my $size = $collection->size; - -Number of elements in collection. - -=head2 sort - - my $new = $collection->sort; - my $new = $collection->sort(sub {...}); - -Sort elements based on return value of callback and create a new collection -from the results. - - # Sort values case-insensitive - my $case_insensitive = $collection->sort(sub { uc($a) cmp uc($b) }); - -=head2 tap - - $collection = $collection->tap(sub {...}); - -Equivalent to L. - -=head2 to_array - - my $array = $collection->to_array; - -Turn collection into array reference. - -=head2 uniq - - my $new = $collection->uniq; - my $new = $collection->uniq(sub {...}); - my $new = $collection->uniq($method); - my $new = $collection->uniq($method, @args); - -Create a new collection without duplicate elements, using the string -representation of either the elements or the return value of the -callback/method. - - # Longer version - my $new = $collection->uniq(sub { $_->$method(@args) }); - - # "foo bar baz" - DOM::Tiny::Collection->new('foo', 'bar', 'bar', 'baz')->uniq->join(' '); - - # "[[1, 2], [2, 1]]" - DOM::Tiny::Collection->new([1, 2], [2, 1], [3, 2])->uniq(sub{ $_->[1] })->to_array; - -=head1 BUGS - -Report any issues on the public bugtracker. - -=head1 AUTHOR - -Dan Book - -=head1 COPYRIGHT AND LICENSE - -This software is Copyright (c) 2015 by Dan Book. - -This is free software, licensed under: - - The Artistic License 2.0 (GPL Compatible) - -=head1 SEE ALSO - -L diff --git a/lib/DOM/Tiny/_Collection.pm b/lib/DOM/Tiny/_Collection.pm new file mode 100644 index 0000000..a053563 --- /dev/null +++ b/lib/DOM/Tiny/_Collection.pm @@ -0,0 +1,113 @@ +package DOM::Tiny::_Collection; + +use strict; +use warnings; +use Carp 'croak'; +use List::Util; +use Scalar::Util 'blessed'; + +our $VERSION = '0.001'; + +=for Pod::Coverage *EVERYTHING* + +=cut + +sub new { + my $class = shift; + return bless [@_], ref $class || $class; +} + +sub TO_JSON { [@{shift()}] } + +sub compact { + my $self = shift; + return $self->new(grep { defined && (ref || length) } @$self); +} + +sub each { + my ($self, $cb) = @_; + return @$self unless $cb; + my $i = 1; + $_->$cb($i++) for @$self; + return $self; +} + +sub first { + my ($self, $cb) = (shift, shift); + return $self->[0] unless $cb; + return List::Util::first { $_ =~ $cb } @$self if ref $cb eq 'Regexp'; + return List::Util::first { $_->$cb(@_) } @$self; +} + +sub flatten { $_[0]->new(_flatten(@{$_[0]})) } + +sub grep { + my ($self, $cb) = (shift, shift); + return $self->new(grep { $_ =~ $cb } @$self) if ref $cb eq 'Regexp'; + return $self->new(grep { $_->$cb(@_) } @$self); +} + +sub join { + join $_[1] // '', map {"$_"} @{$_[0]}; +} + +sub last { shift->[-1] } + +sub map { + my ($self, $cb) = (shift, shift); + return $self->new(map { $_->$cb(@_) } @$self); +} + +sub reduce { + my $self = shift; + @_ = (@_, @$self); + goto &List::Util::reduce; +} + +sub reverse { $_[0]->new(reverse @{$_[0]}) } + +sub shuffle { $_[0]->new(List::Util::shuffle @{$_[0]}) } + +sub size { scalar @{$_[0]} } + +sub slice { + my $self = shift; + return $self->new(@$self[@_]); +} + +sub sort { + my ($self, $cb) = @_; + + return $self->new(sort @$self) unless $cb; + + my $caller = caller; + no strict 'refs'; + my @sorted = sort { + local (*{"${caller}::a"}, *{"${caller}::b"}) = (\$a, \$b); + $a->$cb($b); + } @$self; + return $self->new(@sorted); +} + +sub tap { + my ($self, $cb) = (shift, shift); + $_->$cb(@_) for $self; + return $self; +} + +sub to_array { [@{shift()}] } + +sub uniq { + my ($self, $cb) = (shift, shift); + my %seen; + return $self->new(grep { !$seen{$_->$cb(@_)}++ } @$self) if $cb; + return $self->new(grep { !$seen{$_}++ } @$self); +} + +sub _flatten { + map { _ref($_) ? _flatten(@$_) : $_ } @_; +} + +sub _ref { ref $_[0] eq 'ARRAY' || blessed $_[0] && $_[0]->isa(__PACKAGE__) } + +1; diff --git a/t/collection.t b/t/collection.t index 0c6332f..b455ba1 100644 --- a/t/collection.t +++ b/t/collection.t @@ -1,10 +1,10 @@ use strict; use warnings; use Test::More; -use DOM::Tiny::Collection; +use DOM::Tiny::_Collection; use JSON::PP (); -sub c { DOM::Tiny::Collection->new(@_) } +sub c { DOM::Tiny::_Collection->new(@_) } # Array is c(1, 2, 3)->[1], 2, 'right result';