Pregunta

Me han descargado algunas tareas de mantenimiento en un par de scripts de Perl. Uno de los requisitos es para descargar un par de docenas de archivos (HTTP) en paralelo. Fui a buscar en CPAN para la solución más fácil y encontré este módulo llamado IO :: Lambda: :. HTTP

Por desgracia, no tengo absolutamente ninguna experiencia con la programación funcional (y principiante-nivel de experiencia Perl), por lo que mientras veo que todos los ejemplos funcionan como se documenta, no puedo modificar cualquiera de ellos para satisfacer mis necesidades.

Por ejemplo, la muestra que viene con el módulo:

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

funciona como se anuncia, pero no puedo por la vida de a averiguar cómo modificar ya sea el 'objeto' o ejemplos implícitos '' debe limitarse a casos paralelos N como el siguiente de la sinopsis 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);

Alguien me puede mostrar un ejemplo de lo que el código se vería así lambda dada la restricción anterior (por ejemplo límite de N instancias)?

Además, ¿cuál es la mejor manera de comenzar a aprender la programación funcional? Parece totalmente ajeno a mí.

¿Fue útil?

Solución

Hay buenas otras opciones que IO :: Lambda para esta tarea, por ejemplo AnyEvent: : HTTP . Ver esta pregunta SO anterior .

A pesar de que estoy familiarizado con la programación funcional, lo anterior IO :: Lambda código de ejemplo parece bastante difícil de entender para mí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top