Question

J'ai été déchargé des tâches de maintenance sur deux scripts Perl. L'une des conditions est de télécharger deux fichiers douzaine (HTTP) en parallèle. Je suis allé à la recherche sur CPAN pour la solution la plus simple et a trouvé ce module appelé

Malheureusement, je n'ai absolument aucune expérience avec la programmation fonctionnelle (et de l'expérience Perl débutant niveau), donc quand je vois que tous les exemples fonctionneront comme indiqué, je ne peux pas modifier vraiment l'un d'eux pour répondre à mes besoins.

Par exemple, l'échantillon qui vient avec le module:

#!/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;
}

fonctionne comme prévu, mais je ne peux pas pour la vie de me comprendre comment modifier soit les exemples « objet » ou « implicite » pour se limiter à N instances parallèles comme ce qui suit du synopsis de IO :: Lambda:

# 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);

Quelqu'un peut-il me montrer un exemple de ce que le code lambda ressemblerait donné la contrainte ci-dessus (limite aux cas par exemple N)?

En outre, quelle est la meilleure façon de commencer à apprendre la programmation fonctionnelle? Il semble tout à fait étranger à moi.

Était-ce utile?

La solution

Il y a de bonnes options autres que IO :: Lambda pour cette tâche, par exemple AnyEvent: : HTTP . Voir cette question précédente SO .

Même si je suis familier avec la programmation fonctionnelle, ci-dessus IO :: exemple de code Lambda semble plutôt difficile à comprendre pour moi.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top