Perlの衰退議論について一言言っておくか
- 作者: 前橋和弥
- 出版社/メーカー: 技術評論社
- 発売日: 2009/06/20
- メディア: 大型本
- 購入: 9人 クリック: 211回
- この商品を含むブログ (25件) を見る
Perl衰退に関する最近の話
最近熱が上がっているPerlの衰退の話についてですが、そもそもこーゆー議論に意味ってあるんですかね?どうも信者とそうでない人の言い合いとしか周りからは見れません。僕はPerl信者でも無ければ、Perlを憎んでもいない立場の人間です。以下では個人的に気になったPerlの現状を数値で見直し、Perlを嫌う理由、Perlの使いどころというのを書きたいと思います。
Perlの現状を数値で調査した
CPANのPackage数はPypiに抜かれている
The Comprehensive Perl Archive Network - www.cpan.org
PyPI - the Python Package Index : Python Package Index
Perlをみんなが使った理由としてCPANの充実があったと思います。CPANで検索すれば何かしらライブラリが見つかり、Perlスクリプトの中でuseすれば簡単に利用できたのですごく重宝されています。少し前まではCPANの方がPypiよりもPackage数が多かったことを確認していたのですが、ここ最近では単純なPackage数の比較ではPypiが勝っています。2013/3/10現時点でのPackage登録数はCPANが27033、Pypiは28848です。authorの数も気になるところですが、CPANは10470、Pypiは不明でした。
Perlを嫌う理由を考えた
Perlを嫌う理由は言語としてのIFが分かりづらい点にあると思います。細かい例を挙げると沢山出てきそうなので、ここでは配列操作の例を書いておきます。
配列の存在確認や重複削除
Perlで配列から特定の値を抜き出したい時、値が含まれるかどうかの判定をする時、要素の重複を削除したい時にforeachの繰り返しを使わずに書く手段としてgrepを使います。以下それぞれのサンプルを書きますが、普通の人はgrep{ $_ eq $search } @array1やgrep { !$count{$_}++ } @arrayなどの記述を直ぐに思いつかないはずです。こういったものがperlの可読性を下げている要因の一つかと思うのですが、たった1行の追加で強力なことが出来てしまいます。
#!/usr/bin/env perl my @array = ( 'perl', 'php', 'java', 'python' ); my $search = 'perl'; my @result = grep( /$search/, @array ); foreach( @result ) { print $_ . " "; }perl#!/usr/bin/env perl my @array1 = ( 'perl', 'php', 'java', 'python' ); my @array2 = ( 'php', 'java', 'python' ); my $search = 'perl'; if( grep{ $_ eq $search } @array1 ) { print "array1 $search is Exists\n"; } if( grep{ $_ eq $search } @array2 ) { print "array2 $search is Exists\n"; }array1 perl is Exists#!/usr/bin/env perl my @array = ( 'perl', 'php', 'java', 'java', 'php' ); my %count; @array = grep { !$count{$_}++ } @array; foreach( @array ) { print $_ . " " }perl php java上の例をPythonで記述してみます。Pythonは配列に要素が含まれるかどうかをinで検知してくれます。重複削除は配列をsetに変換するというテクニックが必要なのでこれまた直感的かと言われると微妙なところですが、Perlよりは分かりやすいかと思っています。
#!/usr/bin/env python # -*- coding: utf-8 -*- array = ['perl','php','java'] search = 'perl' result = [x for x in array if x == search ] for i in result: print i,perl#!/usr/bin/env python # -*- coding: utf-8 -*- array = ['perl','php','java'] search = 'perl' if search in array: print search + ' is Exists'perl is Exists#!/usr/bin/env python # -*- coding: utf-8 -*- array = ['perl','php','java','java','php'] result = sorted(set(array),key=array.index) for i in result: print i,perl php javaその他 FWが充実していない
サーバサイドをPerlで書いている人って本当に少ないと思います。僕の周りではPerlで書いているというのを聞いたこと無いです。その一つとしてWebFWの種類が少ないのとそれらが流行らなかったことが原因と考えています。僕が知っている限りだとしかCatalystとMojoliciousしか知らないんですが、Webで使えるFrameworkが他にも存在するのでしょうか?RubyもRails一択じゃんと言われるとそうなんですが、PHPやPythonと比較するとFrameworkの充実は劣る気がしています。
Catalyst | Perl MVC web application framework
Mojolicious - Perl real-time web framework
Perlの使いどころ
ワンライナーの置換はPerlの一択
ファイル内の記述を特定のルールで置換したい場合はPerlの一択だと思います。sed (コンピュータ) - Wikipedia なんていう置換コマンドもありますが、正規表現の使い方が微妙です。Perlコマンドの正規表現はsedよりも強力にサポートされています。Perlの置換コマンドは以下のような感じで利用します。currentのディレクトリに存在するファイル全部に適用したい場合は*で、階層的に実施したい場合は*/*のように定義します。階層的な置換はfind -execを使っても出来きます。
$ perl -i.bak -pe 's/foo/bar/g' * $ perl -i.bak -pe 's/foo/bar/g' */* $ find . -type f -exec perl -i.bak -pe 's/foo/bar/g' {} \;Hadoop StreamingでPerlを使う
naoya/mapreduce-lite · GitHub
僕の会社ではHadoop Streamingを利用する場合はPerlを使うことがほとんどです。理由としては昔からApacheのログ解析モジュールや集計プログラムをPerlで書いていて、それをHadoop StreamingのMap/Reduceでも利用しているという流れだと思います。CPANなどのモジュールも-fileオプションやDistributedCacheを利用すればHadoop Streamingで使えます。当然柔軟なHadoop処理を書きたい場合はJavaで行うべきですが、単純な集計はScript言語で書くとなるとrubyより処理速度が速いとされるPerlで書くのが良いのでは無いでしょうか。以下はwordcountのHadoop Streamingの例です。#!/usr/bin/env perl # mapper.pl use strict; use warnings; while( <> ) { chomp $_; my @tokens = split( /\s|\.|,|\?/, $_ ); foreach( @tokens ) { $_ =~ s/(“|”|-)//g; if( $_ ne "" && $_ ne " " ) { print $_ . "\t" . 1 . "\n"; } }#!/usr/bin/env perl # reducer.pl use strict; use warnings; my %word_hash = (); while( <> ) { chomp $_; my @tokens = split( /\t/, $_ ); my $word = $tokens[0]; if( !defined( $word_hash{$word} ) ) { $word_hash{$word} = 0; } $word_hash{$word}++; } foreach my $word ( sort keys %word_hash ) { print $word . "\t" . $word_hash{$word} . "\n"; }#!/bin/sh job_name='"SocialNetwrok WordCount"' hadoop='/usr/lib/hadoop-0.20/bin/hadoop' streaming_jar='/usr/lib/hadoop-0.20/contrib/streaming/hadoop-streaming-0.20.2-cdh3u5.jar' input_path='socialnetwork/input' output_path='socialnetwork/ouput' mapper='mapper.pl' reducer='reducer.pl' base_path=`pwd` reducer_num=1 echo $hadoop fs -rmr $output_path echo $hadoop jar $streaming_jar -D mapred.job.name=$job_name -D mapred.reduce.task=$reducer_num -input $input_path -output $output_path -mapper $mapper -reducer $reducer -file $base_path/$mapper -file $base_path/$reducer