<commit_before>package Mojo::Collection;
use Mojo::Base -strict;

use Carp 'croak';
use Exporter 'import';
use List::Util;
use Mojo::ByteStream;
use Mojo::Util 'deprecated';
use Scalar::Util 'blessed';

# DEPRECATED in Tiger Face!
use overload '""' => sub {
  deprecated 'Stringification support in Mojo::Collection is DEPRECATED';
  shift->join("\n");
};
use overload bool => sub {1}, fallback => 1;

our @EXPORT_OK = ('c');

# DEPRECATED in Tiger Face!
sub AUTOLOAD {
  deprecated 'Mojo::Collection::AUTOLOAD is DEPRECATED in favor of'
    . ' Mojo::Collection::map';
  my $self = shift;
  my ($package, $method) = our $AUTOLOAD =~ /^(.+)::(.+)$/;
  croak "Undefined subroutine &${package}::$method called"
    unless blessed $self && $self->isa(__PACKAGE__);
  return $self->map($method, @_);
}

# DEPRECATED in Tiger Face!
sub DESTROY { }

sub c { __PACKAGE__->new(@_) }

sub compact {
  $_[0]->new(grep { defined && (ref || length) } @{$_[0]});
}

sub each {
  my ($self, $cb) = @_;
  return @$self unless $cb;
  my $i = 1;
  $_->$cb($i++) for @$self;
  return $self;
}

sub first {
  my ($self, $cb) = @_;
  return $self->[0] unless $cb;
  return List::Util::first { $cb->($_) } @$self if ref $cb eq 'CODE';
  return List::Util::first { $_ =~ $cb } @$self;
}

sub flatten { $_[0]->new(_flatten(@{$_[0]})) }

sub grep {
  my ($self, $cb) = @_;
  return $self->new(grep { $cb->($_) } @$self) if ref $cb eq 'CODE';
  return $self->new(grep { $_ =~ $cb } @$self);
}

sub join {
  Mojo::ByteStream->new(join $_[1] // '', map {"$_"} @{$_[0]});
}

sub last { shift->[-1] }

sub map {
  my ($self, $cb) = (shift, shift);
  return $self->new(map { $_->$cb(@_) } @$self);
}

sub new {
  my $class = shift;
  return bless [@_], ref $class || $class;
}

# DEPRECATED in Tiger Face!
sub pluck {
  deprecated
    'Mojo::Collection::pluck is DEPRECATED in favor of Mojo::Collection::map';
  my ($self, $key) = (shift, shift);
  return $self->new(map { ref eq 'HASH' ? $_->{$key} : $_->$key(@_) } @$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 { shift->Mojo::Base::tap(@_) }

sub uniq {
  my %seen;
  return $_[0]->new(grep { !$seen{$_}++ } @{$_[0]});
}

sub _flatten {
  map { _ref($_) ? _flatten(@$_) : $_ } @_;
}

sub _ref { ref $_[0] eq 'ARRAY' || blessed $_[0] && $_[0]->isa(__PACKAGE__) }

1;

=encoding utf8

=head1 NAME

Mojo::Collection - Collection

=head1 SYNOPSIS

  use Mojo::Collection;

  # Manipulate collection
  my $collection = Mojo::Collection->new(qw(just works));
  unshift @$collection, 'it';

  # Chain methods
  $collection->map(sub { ucfirst })->shuffle->each(sub {
    my ($word, $count) = @_;
    say "$count: $word";
  });

  # Stringify collection
  say $collection->join("\n");

  # Use the alternative constructor<commit_msg>better collection example<commit_after>package Mojo::Collection;
use Mojo::Base -strict;

use Carp 'croak';
use Exporter 'import';
use List::Util;
use Mojo::ByteStream;
use Mojo::Util 'deprecated';
use Scalar::Util 'blessed';

# DEPRECATED in Tiger Face!
use overload '""' => sub {
  deprecated 'Stringification support in Mojo::Collection is DEPRECATED';
  shift->join("\n");
};
use overload bool => sub {1}, fallback => 1;

our @EXPORT_OK = ('c');

# DEPRECATED in Tiger Face!
sub AUTOLOAD {
  deprecated 'Mojo::Collection::AUTOLOAD is DEPRECATED in favor of'
    . ' Mojo::Collection::map';
  my $self = shift;
  my ($package, $method) = our $AUTOLOAD =~ /^(.+)::(.+)$/;
  croak "Undefined subroutine &${package}::$method called"
    unless blessed $self && $self->isa(__PACKAGE__);
  return $self->map($method, @_);
}

# DEPRECATED in Tiger Face!
sub DESTROY { }

sub c { __PACKAGE__->new(@_) }

sub compact {
  $_[0]->new(grep { defined && (ref || length) } @{$_[0]});
}

sub each {
  my ($self, $cb) = @_;
  return @$self unless $cb;
  my $i = 1;
  $_->$cb($i++) for @$self;
  return $self;
}

sub first {
  my ($self, $cb) = @_;
  return $self->[0] unless $cb;
  return List::Util::first { $cb->($_) } @$self if ref $cb eq 'CODE';
  return List::Util::first { $_ =~ $cb } @$self;
}

sub flatten { $_[0]->new(_flatten(@{$_[0]})) }

sub grep {
  my ($self, $cb) = @_;
  return $self->new(grep { $cb->($_) } @$self) if ref $cb eq 'CODE';
  return $self->new(grep { $_ =~ $cb } @$self);
}

sub join {
  Mojo::ByteStream->new(join $_[1] // '', map {"$_"} @{$_[0]});
}

sub last { shift->[-1] }

sub map {
  my ($self, $cb) = (shift, shift);
  return $self->new(map { $_->$cb(@_) } @$self);
}

sub new {
  my $class = shift;
  return bless [@_], ref $class || $class;
}

# DEPRECATED in Tiger Face!
sub pluck {
  deprecated
    'Mojo::Collection::pluck is DEPRECATED in favor of Mojo::Collection::map';
  my ($self, $key) = (shift, shift);
  return $self->new(map { ref eq 'HASH' ? $_->{$key} : $_->$key(@_) } @$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 { shift->Mojo::Base::tap(@_) }

sub uniq {
  my %seen;
  return $_[0]->new(grep { !$seen{$_}++ } @{$_[0]});
}

sub _flatten {
  map { _ref($_) ? _flatten(@$_) : $_ } @_;
}

sub _ref { ref $_[0] eq 'ARRAY' || blessed $_[0] && $_[0]->isa(__PACKAGE__) }

1;

=encoding utf8

=head1 NAME

Mojo::Collection - Collection

=head1 SYNOPSIS

  use Mojo::Collection;

  # Manipulate collection
  my $collection = Mojo::Collection->new(qw(just works));
  unshift @$collection, 'it';
  say $collection->join("\n");

  # Chain methods
  $collection->map(sub { ucfirst })->shuffle->each(sub {
    my ($word, $count) = @_;
    say "$count: $word";
  });

  # Use the alternative constructor
{'fraction_non_alphanumeric': 0.22875916870415647, 'fraction_numerical': 0.007640586797066014, 'mean_word_length': 3.7948717948717947, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3269747', 'n_tokens_mistral': 2631, 'n_tokens_neox': 2588, 'n_words': 661}