Существует ли решение для Perl для ленивых списков эта сторона Perl 6?

Если кому-то нужно перебирать объекты массива с условием:

var arrayObjects = [{"building":"A", "status":"good"},{"building":"B","status":"horrible"}];

for (var i=0; i< arrayObjects.length; i++) {
  console.log(arrayObjects[i]);
  
  for(key in arrayObjects[i]) {      
    
      if (key == "status" && arrayObjects[i][key] == "good") {
        
          console.log(key + "->" + arrayObjects[i][key]);
      }else{
          console.log("nothing found");
      }
   }
}

11
задан tshepang 7 March 2014 в 19:16
поделиться

8 ответов

Как упомянуто ранее, для (каждого) нетерпеливый цикл, таким образом, он хочет оценить весь список перед запуском.

Для простоты я рекомендовал бы использовать объект итератора или закрытие вместо того, чтобы пытаться иметь лениво оцененный массив. В то время как можно использовать связь, чтобы иметь лениво оцененный бесконечный список, можно столкнуться с проблемами, если Вы когда-нибудь спрашиваете (прямо или косвенно, как в foreach выше) для всего списка (или даже размер всего списка).

Не пишущий полный класс или с помощью любых модулей, можно сделать простую фабрику итератора только при помощи закрытий:

sub make_iterator {
    my ($value, $max, $step) = @_;

    return sub {
        return if $value > $max;    # Return undef when we overflow max.

        my $current = $value;
        $value += $step;            # Increment value for next call.
        return $current;            # Return current iterator value.
    };
}

И затем использовать его:

# All the even numbers between 0 -  100.
my $evens = make_iterator(0, 100, 2);

while (defined( my $x = $evens->() ) ) {
    print "$x\n";
}

Существует также Связь:: Массив:: Ленивый модуль на CPAN, который предоставляет намного более богатый и более полный интерфейс ленивым массивам. Я не использовал модуль сам, таким образом, Ваш пробег может варьироваться.

Всего наилучшего,

Paul

13
ответ дан 3 December 2019 в 01:07
поделиться

Используйте итератор или рассмотрите использование Связи:: LazyList от CPAN (который немного датирован).

3
ответ дан 3 December 2019 в 01:07
поделиться

Существует по крайней мере один особый случай, где для и foreach были оптимизированы для не генерации целого списка сразу. И это - оператор диапазона. Таким образом, у Вас есть опция высказывания:

for my $i (0..$#list) {
  my $item = some_function($list[$i]);
  ...
}

и это выполнит итерации через массив, преобразованный однако Вам нравится, не создавая длинный список значений впереди.

Если Вы желаете своего положения карты к числам элементов возвращаемой переменной, Вы могли бы сделать это вместо этого:

for my $i (0..$#array) {
  for my $item (some_function($array[$i])) {
    ...
  }
}

Если Вы желаете более распространяющейся лени, чем это, то Ваш наилучший вариант состоит в том, чтобы изучить, как использовать закрытия для генерации ленивых списков. Превосходная книга MJD Perl Высшего порядка может обойти Вас через те методы. Однако будьте, предупредил, что они включат намного большие изменения в Вашем коде.

5
ответ дан 3 December 2019 в 01:07
поделиться

Если Вы хотите составить ленивые списки, необходимо будет записать собственный итератор. После того как у Вас есть это, можно использовать что-то как Объект:: Выполните итерации, который имеет осведомленные об итераторе версии map и grep. Смотрите на источник для того модуля: это довольно просто, и Вы будете видеть, как записать Ваши собственные осведомленные об итераторе подпрограммы.

Удача, :)

7
ответ дан 3 December 2019 в 01:07
поделиться

[Заметка на полях: знайте, что каждый отдельный шаг вдоль map/grep цепочки нетерпелив. Если Вы даете ему большой список внезапно, Ваши проблемы запускаются намного раньше, чем в финале foreach.]

То, что можно сделать, чтобы избежать, чтобы полное переписало, должно перенести цикл с внешним циклом. Вместо того, чтобы писать это:

for my $item ( map { ... } grep { ... } map { ... } @list ) { ... }

… пишут это как это:

while ( my $input = calculcate_next_element() ) {
    for my $item ( map { ... } grep { ... } map { ... } $input ) { ... }
}

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

9
ответ дан 3 December 2019 в 01:07
поделиться

Я задал подобный вопрос по perlmonks.org, и BrowserUk дал действительно хорошую платформу в его ответе. В основном удобный способ получить отложенные вычисления состоит в том, чтобы породить потоки для вычисления, по крайней мере, пока Вы уверены, что хотите результаты, Просто Не Теперь. Если Вы захотите, чтобы отложенные вычисления не уменьшили задержку, но избежали вычислений, то мой подход не поможет, потому что это полагается на модель передачи, не модель приема. Возможно с помощью Corooutines, можно превратить этот подход в (однопоточную) модель приема также.

При обдумывании этой проблемы я также исследовал связывание массива к результатам потока для создания процесса выполнения программы Perl больше как map, но до сих пор, мне нравится мой API представления parallel "ключевое слово" (скрытый конструктор Object) и затем вызывающие методы для результата. Более зарегистрированная версия кода будет отправлена как ответ на тот поток и возможно выпущена на CPAN также.

3
ответ дан 3 December 2019 в 01:07
поделиться

Если я помню правильно, for/foreach действительно получают целый список сначала так или иначе, таким образом, лениво оцененный список был бы прочитан полностью, и затем он начнет выполнять итерации через элементы. Поэтому я думаю, что нет никакого другого пути, чем использование некоторое время цикла. Но я могу быть неправым.

Преимущество некоторое время цикла состоит в том, что можно фальсифицировать сенсацию лениво оцененного списка со ссылкой кода:

my $list = sub { return calculate_next_element };
while(defined(my $element = &$list)) {
    ...
}

В конце концов, я предполагаю, что связь является настолько тесной, как можно войти в Perl 5.

2
ответ дан 3 December 2019 в 01:07
поделиться

Приносит это обратно из мертвых упомянуть, что я только что написал модуль Список :: Gen на CPAN , который имеет именно то, что искал плакат Для:

use List::Gen;

for my $item ( @{gen { ... } \@list} ) {...}

Все вычисления списков ленивы, и есть эквиваленты карты / GREP вместе с несколькими другими функциями.

Каждая из функций возвращает «генератор», который является ссылкой на связанный массив. Вы можете использовать связанный массив напрямую, или есть куча методов аксессуаров, таких как итераторы для использования.

4
ответ дан 3 December 2019 в 01:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: