2010-12-07 4 views
4

私はいくつかのPerlスクリプトでいくつかのメンテナンス作業をオフロードしています。要件の1つは、数十のファイル(HTTP)を並行してダウンロードすることです。私は最も簡単な解決策のためにCPANを調べて、IO::Lambda::HTTPと呼ばれるこのモジュールを見つけました。IO :: Lambda in Perl

残念ながら、私は関数型プログラミング(および初心者レベルの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; 
} 

作品

が宣伝として、私は私の人生のために「オブジェクト」または「暗黙の」のいずれかを変更する方法を見つけ出すことはできませんIOから次のようなN個の並列インスタンス::ラムダの概要に限定される例:

# 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インスタンスに例えば制限)指定されたどのように見えるかの例を表示することができます?

さらに、関数型プログラミングの学習を開始するにはどうすればよいでしょうか?私にとって全く異質なようだ。

答えて

1

このタスクでは、IO :: Lambda以外のオプションがあります。たとえば、AnyEvent::HTTPです。 this previous SO questionを参照してください。

私は関数型プログラミングに精通していますが、上記のIO :: Lambdaサンプルコードはわかりにくいです。

+0

合意しました。これは重いものです。 PerlとFPマスタリングの初心者のために、IO :: Lambdaのアプローチは非常にイライラします。 AnyEvent :: HTTPは使用可能に見えますが、並列要求の数を制限するためにはまだ何らかの作業が必要です。 – ivancho