Примеры ленивых методов оценки в Perl 5? - PullRequest
5 голосов
/ 08 декабря 2010

Я считаю, что одна из самых интересных функций как в Haskell, так и в Perl6 - это возможность откладывать расчетные значения до тех пор, пока они действительно не понадобятся.

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

  • , принимая ссылку на @_ в подпрограмме, создает ссылку на массив, которая связывается с идентификаторами в ее списке аргументов, даже если некоторые из этих идентификаторов еще не содержат значений.
  • возвращает перегруженные / связанные объекты из таких подпрограмм, которые содержат \@_ внутри, а затем разыменовывает его при необходимости. (и есть различные CPAN-модули, которые абстрагируют от деталей связи / перегрузки)

Я экспериментировал с различными методами ленивого программирования на Perl (в работах у меня есть модуль, в котором реализована немалая часть Прелюдии Haskell в Perl5 (такие вещи, как ко-рекурсия: уже работает)). Но у меня есть ощущение, что в коде скрываются некоторые тонкие ошибки, которые могут проявляться, когда функции используются в больших выражениях / программах.

Так что мне интересно, есть ли какие-нибудь хорошие примеры (CPAN / блоги / книги), которые кто-нибудь знает об этом, использующих Haskell / Perl6 как лень в Perl5? В частности, я хотел бы прочитать любой код значительного размера, который использует этот тип лени.

Мне также было бы интересно узнать, сталкивался ли кто-нибудь с какими-либо хитростями или неразрешимыми проблемами, связанными с реализацией отложенной оценки в Perl 5.

Ответы [ 3 ]

9 голосов
/ 08 декабря 2010

Perl высшего порядка (свободно доступен онлайн ) имеет главу под названием «Бесконечные потоки». Может быть, это хорошая отправная точка.

6 голосов
/ 08 декабря 2010

Ну, Moose делает это с отложенная загрузка атрибутов :

Методы по умолчанию и компоновщик
Атрибуты могутимеют значения по умолчанию, и Moose предоставляет два способа указать это значение по умолчанию.
["default" и "builder" описанные опции ...]

Laziness
Moose позволяет вамотложить заполнение атрибута, сделав атрибут «ленивым»:

has 'size' => (
    is      => 'ro',
    lazy    => 1,
    builder => '_build_size',
);

Когда «ленивый» имеет значение «истина», значение по умолчанию не генерируется до вызова метода считывателя, а не во время создания объекта.Есть несколько причин, по которым вы можете сделать это.

Во-первых, если значение по умолчанию для этого атрибута зависит от некоторых других атрибутов, тогда атрибут должен быть «ленивым».Во время создания объекта значения по умолчанию не генерируются в предсказуемом порядке, поэтому вы не можете рассчитывать на какой-либо другой атрибут, который будет заполнен при создании значения по умолчанию.

Во-вторых, часто нет причин рассчитывать значение по умолчанию до того, как оно потребуется.Создание атрибута «ленивый» позволяет вам отложить стоимость, пока атрибут не понадобится.Если атрибут никогда не нужен, вы экономите некоторое время процессора.

Мы рекомендуем сделать любой атрибут с компоновщиком или нетривиальным по умолчанию "ленивым" как само собой разумеющееся.

4 голосов
/ 08 декабря 2010

Я думаю, что самая большая проблема - это «Битва магии». Когда вы пытаетесь что-то сделать, вы думаете, что это элегантно, а какой-то другой автор модуля пытается сделать что-то, что, по их мнению, является элегантным, а результат - неопределенным. Чья магия побеждает?

Поскольку всегда можно заглянуть за магию другой переменной или даже непреднамеренно разочаровать ее, магия никогда не бывает пуленепробиваемой.

Если бы вы могли достичь 100% ортогональности с помощью исчерпывающего тестирования, вы могли бы отдохнуть легче ... возможно.

...