LINUX.ORG.RU

История изменений

Исправление Jini, (текущая версия) :

Быстрее, экономичнее, элегантнее будет не экономить на пробелах, а завернуть это в простую функцию. Почитай про bottom-up программирование. Вот первое что пришло в голову, возможно, есть ещё проще варианты:

use Data::Dumper;

sub make_intervals {
  my ($m, $c) = @_;
  my @result;
  my $i = 0;
  while ($m > 0) {
    push @result, [ $i, $i + $c - 1 ];
    $i += $c;
    $m -= $c;
  };
  $result[$#result][1] += $m if @result;
  \@result;
};

print Dumper make_intervals 90, 15;

Касательно предыдущей части, попробуй использовать итераторы. На CPANе мне попадались подходящие модули, но вообще их можно на коленке делать. Вот пример:

use v5.22;

my $eos = \1; # end of stream designator for igenerate

sub done { $eos };

sub igenerate(&) {
  my ($generator) = @_;
  sub {
    my ($yield) = @_;
    my $value = $generator->();
    return if $value == $eos;
    $yield->($value);
    __SUB__;
  };
};

sub imap(&@) {
  my ($function, $iterator) = @_;
  sub {
    my ($yield) = @_;
    $iterator = $iterator->(sub { $yield->($function->(@_)) });
    __SUB__ if $iterator;
  };
};

sub igather(&@) {
  my ($gatherer, $iterator) = @_;
  $iterator = $iterator->($gatherer) while $iterator;
};

sub iarray {
  my ($array) = @_;
  my $i = 0;
  igenerate { $i < @$array ? $array->[$i++] : done };
};

sub isplice {
  my ($n, $iterator) = @_;
  my @args;
  sub {
    my ($yield) = @_;
    my $i = 0;
    while ($iterator && $i < $n) {
      $iterator = $iterator->(sub { $args[$i++] = $_[0] });
    };
    $#args = $i - 1;
    $yield->(@args) if @args;
    __SUB__ if $iterator;
  };
};

igather { say "@_" } imap { map { $_ * 2 } @_ } isplice 5, iarray [ 1..20 ];

Исходная версия Jini, :

Быстрее, экономичнее, элегантнее будет не экономить на пробелах, а завернуть это в простую функцию. Почитай про bottom-up программирование. Вот первое что пришло в голову, возможно, есть ещё проще варианты:

use Data::Dumper;

sub make_intervals {
  my ($m, $c) = @_;
  my @result;
  my $i = 0;
  while ($m > 0) {
    push @result, [ $i, $i + $c - 1 ];
    $i += $c;
    $m -= $c;
  };
  $result[$#result][1] += $m if @result;
  \@result;
};

print Dumper make_intervals 90, 15;

Касательно предыдущей части, попробуй использовать итераторы. На CPANе мне попадались подходящие модули, но вообще их можно на коленке делать. Вот пример:

use v5.22;

my $eos = \1; # end of stream designator for igenerate

sub done { $eos };

sub igenerate(&) {
  my ($generator) = @_;
  sub {
    my ($yield) = @_;
    my $value = $generator->();
    return if $value == $eos;
    $yield->($value);
    __SUB__;
  };
};

sub imap(&@) {
  my ($function, $iterator) = @_;
  sub {
    my ($yield) = @_;
    $iterator = $iterator->(sub { $yield->($function->(@_)) });
    __SUB__ if $iterator;
  };
};

sub igather(&@) {
  my ($gatherer, $iterator) = @_;
  $iterator = $iterator->($gatherer) while $iterator;
};

sub iarray {
  my ($array) = @_;
  my $i = 0;
  igenerate { $i < @$array ? $array->[$i++] : done };
};

sub isplice($@) {
  my ($n, $iterator) = @_;
  my @args;
  sub {
    my ($yield) = @_;
    my $i = 0;
    while ($iterator && $i < $n) {
      $iterator = $iterator->(sub { $args[$i++] = $_[0] });
    };
    $#args = $i - 1;
    $yield->(@args) if @args;
    __SUB__ if $iterator;
  };
};

igather { say "@_" } imap { map { $_ * 2 } @_ } isplice 5, iarray [ 1..20 ];