Вопрос

Я был объявлен некоторые задачи обслуживания на пару сценариев Perl. Одним из требований является скачать пару десятков файлов (HTTP) параллельно. Я пошел смотреть на CPAN для самых простых решений и нашел этот модуль под названием IO :: лямбда :: http.

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

Например, образец, который поставляется с модулем:

#!/usr/bin/perl
# $Id: parallel.pl,v 1.7 2008/05/06 20:41:33 dk Exp $
# 
# This example fetches two pages in parallel, one with http/1.0 another with
# http/1.1 . The idea is to demonstrate three different ways of doing so, by
# using object API, and explicit and implicit loop unrolling
#

use lib qw(./lib);
use HTTP::Request;
use IO::Lambda qw(:lambda);
use IO::Lambda::HTTP qw(http_request);
use LWP::ConnCache;

my $a = HTTP::Request-> new(
  GET => "http://www.perl.com/",
);
$a-> protocol('HTTP/1.1');
$a-> headers-> header( Host => $a-> uri-> host);

my @chain = ( 
  $a, 
  HTTP::Request-> new(GET => "http://www.perl.com/"),
);

sub report
{
  my ( $result) = @_;
  if ( ref($result) and ref($result) eq 'HTTP::Response') {
    print "good:", length($result-> content), "\n";
  } else {
    print "bad:$result\n";
  }
#   print $result-> content;
}

my $style;
#$style = 'object';
#$style = 'explicit';
$style = 'implicit';

# $IO::Lambda::DEBUG++; # uncomment this to see that it indeed goes parallel

if ( $style eq 'object') {
  ## object API, all references and bindings are explicit
  sub handle {
    shift;
    report(@_);
  }
  my $master = IO::Lambda-> new;
  for ( @chain) {
    my $lambda = IO::Lambda::HTTP-> new( $_ );
    $master-> watch_lambda( $lambda, \&handle);
  }
  run IO::Lambda;
} elsif ( $style eq 'explicit') {
  #
  # Functional API, based on context() calls. context is
  # $obj and whatever arguments the current call needs, a RPN of sorts.
  # The context though is not stack in this analogy, because it stays
  # as is in the callback
  #
  # Explicit loop unrolling - we know that we have exactly 2 steps
  # It's not practical in this case, but it is when a (network) protocol
  # relies on precise series of reads and writes
  this lambda {
    context $chain[0];
    http_request \&report;
    context $chain[1];
    http_request \&report;
  };
  this-> wait;
} else {
  # implicit loop - we don't know how many states we need
  # 
  # also, use 'tail'
  this lambda {
    context map { IO::Lambda::HTTP-> new( $_, async_dns => 1 ) } @chain;
    tails { report $_ for @_ };
  };
  this-> wait;
}

Работает как рекламируемая, но я не могу за жизнь меня выяснить, как изменить примеры «объекта» или «неявных», которые будут ограничены n параллельными экземплярами, такие как следующие из IO :: SynaMbda Synopsis:

# http://search.cpan.org/~karasik/IO-Lambda/lib/IO/Lambda.pm
# crawl for all urls in parallel, but keep 10 parallel connections max
print par(10)-> wait(map { http($_) } @hosts);

Может ли кто-нибудь показать мне пример того, как будет выглядеть код лямбда, как указано вышеперечисленное ограничение (например, ограничение в экземпляры N)?

Кроме того, какой лучший способ начать изучать функциональное программирование? Это кажется совершенно чужд для меня.

Это было полезно?

Решение

Есть хорошие другие варианты, чем IO :: лямбда для этой задачи, например, AnyEvent :: http.. Отказ Видеть этот предыдущий настолько вопрос.

Несмотря на то, что я знаком с функциональным программированием, вышеупомянутая IO :: лямбда, пример кода выглядит довольно сложно, чтобы понять мне.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top