MENU

溶けかけてるうさぎ HP GALLERY BLOG TOP RECENT ARTICLES POPULAR ARTICLES ABOUT THIS BLOG

CATEGORY

大学 (140) 仕事 (17) 航空宇宙 (104) 写真 (77) 旅行 (32) 飯・酒 (17) コンピュータ (118) その他 (44)

TAG

ARCHIVE

RECENT

【カメラ】X100 シリーズが好きすぎる(主にリーフシャッタ) 【カメラ】X100V から X100VI に買い替えました 【自宅サーバー】Google Domains から Cloudflare にドメインを移管 【カメラ】FUJIFILM XF レンズのサイズ比較ができるようにしてみた 【写真】自作写真閲覧ページにてフィルムシミュレーションで写真をフィルタできるようにした

【Perl】Perl生誕30周年!

事象発生日:2017-12-18

記事公開日:2017-12-18

アクセス数:23585

この記事は,東京大学航空宇宙工学科/専攻 Advent Calendar 2017向けの記事です.

 

Perl生誕30周年おめでとーー!

Perlってこんな言語だよ!

Perlってとってもいい言語だよ!

Perler増えないかなぁ....

 

トップ画像の出典はこちら

1.Perl生誕30周年!

2017年12月18日は,Perl生誕30周年記念日です.

いやぁ,めでたい.

 

Perl,一番好きなプログラミング言語なんですよね.

このホームページ/ブログシステムは全てフルスクラッチの自作だけれども,サーバーサイドはすべてPerl/CGIで動いています.

 

せっかくの生誕30周年記念日なので何か書きたいけど,文法解説したところでつまらない.

まあ適当にPerlの好きなところとか書いておきますかね.

 

手始めに,あまりにも有名な一節をより引用しておこう.

Perlを単に好きな人にとっては,それは「実用データ取得レポート作成言語」(Practical Extraction and Report Language) にすぎない.

Perlを愛する人にとっては,それは「病的折衷主義のがらくた出力装置」(Pathologically Eclectic Rubbish Lister) である.

 

 

また,この記事の続きとして,「」でワンライナーについて適当に書いているので,ついでに読んでいってください.

 

なお,東京大学航空宇宙工学科/専攻 Advent Calendar 2017の記事説明には,「航空宇宙で最も使われる言語,Perl」って書いてあったけど,あれ,嘘ね.(それはそう.)

学科でPerl使ってる人,僕以外で見たことない....(あんなに布教しているのに....)

2.Perlとは

概要

まあ,まずこれを見てください.

Perlは1987年12月、アメリカのウォール夫妻の元で生を受ける。父のラリーはコンピュータや言語学に精通し、母も中世ルネサンスや言語学を専攻する、高い教養を持つ両親の元で育った。

 

父の教えは厳しかったが、同時に自由でもあった。父は教育の中で、よくこの言葉を口にした。

 

「方法は1つだけじゃない」

(There's more than one way to do it)

 

何かを実現しようと思った時、それを達成する方法は1つだけじゃない。何通りも考えられる。そんな父の教えは、彼女の人格形成に大きな影響を与えた。

 

「こんな風にやってみたらどうだろう」「こうしたらどうなるだろう」そんな好奇心の羽根を広げながら育った彼女は、その延長線上に「発明」という天職を見つけることになる。稀代の女性発明家、Perlの誕生である。

 

彼女が発明家の道に足を踏み出してから20年。生み出してきた発明品は、実に128,890 件にのぼる(2014年1月時点)。あまり役には立たないジョークのようなものから、世界の多くの問題を解決するような有益なものまで、実にさまざまなものを発明している。彼女が作った発明品のオリジナルは、シーパン博物館にすべて寄贈され、誰でも閲覧できるようになっている。

 

今日でもさまざまな発明を続けている彼女だが、役に立つ立たないに関わらず、作りたいと思ったものを作り続ける自身の姿勢を茶化してか「わたしは発明家というよりは、ガラクタ出力装置みたいなものだから」とインタビューに対しては答えている。歯を見せて笑いながらそう語る彼女の姿は、とてもチャーミングである。

 

洋服にはあまりこだわりがないようで、普段は趣味の機械いじりの邪魔にならないような、動きやすいカジュアルなものを着ている。最近よく着ているダウンコートはアメ横のWEGOで買ったそうだ。好きな食べ物はイチゴ。作業に集中して疲れた脳にイチゴは最適なのだと力説している。

 

Perl、C、Scala…プログラミング言語擬人化計画2

この描写はなかなか的を得ていて,Perlをよく表しているんですよね.

次項から,これをふまえてPerlを見ていこうと思います.

Perl誕生の背景

Perlが誕生した1987年ごろ,プログラミング言語としては主にC言語が用いられており,また簡単なテキスト処理には,シェル,sed,awkが用いられていました.

で,まあ,簡単に言っちゃうと,Cとシェルの間がなかったんですよね.

その間の大きなギャップを埋め,さらには今までそれらで書いていたものの一部を簡単に,わかりやすく,低コストで,安全に,移植性が高く書けるようにしてしまおう,っていう感じで生まれたわけです.

TMTOWTDI

Perlのスローガンは,"There's More Than One Way To Do It."(やり方は何通りもある)です.

これは「正しいやり方がいくつ存在してもよい」という考え方で,Perlの柔軟性の高さを表しています.

 

実装方法や書き方はたくさんあり,後述するコードゴルフの発祥もPerl (Perl Golf) でした.

(まあ,このせいで人によって書くコードが全然違って大変だったりするんだけどねw)

 

ここら辺も後述するけど,Perlには多数の略記や特殊変数があって,馴染みのない人にはまるでわからない言語に見えたりするそう.

 

なお,Perlの生みの親であるLarry Wall氏はこんなこと言ってますね

TMTOWTDI(それには何通りもやり方がある。There's More Than One Way To Do It.)がPerlの最大の特徴です。ユーザーは,自分の理解した範囲で自分なりの書き方でコードを書くことができます。たとえばPerlもオブジェクトを扱えますが,他の言語のようにオブジェクトの使用を強制されるわけではありません。自然言語と同じ柔軟性を持っています。さて,Perlプログラムが読みにくいとのことですが,私にとっては日本語も読みにくい言語です(笑)。しかし,あなたにとってはそうではない。つまり言語への理解が深くなれば,自然に読めるようになるということです。Perlが読みにくいと批判する人たちは,Perlを学んでいないのでしょう(笑)。

 

 

ちなみに,というか,比較として他の言語のスローガンも幾つか紹介しておこうかな.

 

僕が生まれて初めてHello, world!を実行した言語であるJavaは,"Write Once, Run Anywhere" ですね.(全然run anywhereじゃないんですけど....とツッコミたいが.)

 

我が学科の学科内共通言語であるPythonは,明確なスローガンはないようだけど,

"There’s only one way to do it." (Perlより後発なのに,Perlに喧嘩売ってんのか?(笑))とか,

"Make each program do one thing well."(UNIX哲学のパクリじゃん.)とか

をよく聞きますね.

 

日本人のまつもとゆきひろ氏作成の言語であり,我が大学の理系の人間は準必修授業「情報科学(現,アルゴリズム入門)」で触れることとなるRubyは,"enjoy programming" ですよね.

RubyはPerlから "Diversity is Good" という文化を引き継いでいるようです

(てか,に「「Matz(まつもと) が Python に満足していれば Ruby は生まれなかったであろう」と公式のリファレンスの用語集で言及されている。」ってあるのおもしろい.)

CPAN

」で引用した文章中にあった,“シーパン博物館”というのはCPAN (Comprehensive Perl Archive Network) のことを言っています.

"194,458 Perl modules in 35,954 distributions, written by 13,329 authors, mirrored on 256 servers."(2017/12/17 現在),だそうです.

 

ここ探せば,欲しいライブラリ,モジュールなんでも出てくるよ.ほんとに.

さすが今年で30周年を向かえる言語なだけあって,膨大なライブラリ,モジュールが作成されているみたいです.

CPANのよさはで熱く語られているので,ぜひこちらを参照.

病的折衷主義のがらくた出力装置

」で引用した文章中にあった,“わたしは発明家というよりは、ガラクタ出力装置みたいなものだから”というのはPerlの略語である「病的折衷主義のがらくた出力装置」(Pathologically Eclectic Rubbish Lister) のことですね.

 

どうしてこう言われているのかは,“Larry Wall氏(Perlの生みの親)がそう言っているから”でしかないけれど,

C,awk,sed,シェルなどのほとんど全ての機能を取り込んでいること
TMTOWTDIという思想により,自分の知っている構文・変数の中で自分流にコードを記述できるので,書き手の個性や知識に合わせて様々なコードが生み出されてしまうこと

とかが所以なんでしょうかね?

 

Larry Wall氏はこんなことも言ったりしています

私は言語学者でもありますから,Perlを自然言語のように,5才の子どもでも70才の老人でもそれぞれのレベルに応じて話せる言語として設計しています。

Perlの未来

残念ながらPerlは現在ではあまり流行っているとは言えず,またあまり注目を浴びるようなこともありません.

でも,それは裏を返せば,“Perlは安定している”ということです.

 

PerlはUNIXであればデフォルトでインストールされているし,高い後方互換性もあります.(僕の好きではない言語であるPython,PHPと違ってね!)

Perlならば,今あるコードはきっと10年後の生誕40周年のときでも,そのままの状態で普通に動いてくれることでしょう.

 

 

一方,改革(?)の動きもあり,2015年にはPerl6というオブジェクト指向スクリプト言語がリリースされました.

Perlはもともとオブジェクト指向ではないので,オブジェクト指向でも書けますが,すこし風変わりな書き方になってしまいます.

Perlの後方互換性を維持したまま,最新の機能を追加するのは難しいこともあり,Perl6は開発されました.

そういうわけでPerl6はPerlと互換性はありません.

 

それ,Python2系とPython3系の関係と同じじゃん...,って思われるかもしれませんが,Perl6はPerl(現在のバージョンは5.x)の次期バージョンではない,とされているのです.

つまり,Perl6はPerlとは全くの別言語扱いなのです.

そう,既存のPerlは永久に不滅なのです.(多分)

3.Perlコードの(僕が気に入っている)特徴

この節では,僕がとくに気に入っているPerlの特徴をいくつか紹介したいと思います.

Sigil

Perlは変数名にSigilをつけます.

そのSigilは,変数型を表しているのではなく,データ構造を表しているところが他の言語と全く異なるところであり,個人的に気に入っているところでもあります.

具体的には,スカラーには$,配列には@,ハッシュ(連想配列,辞書)には%,関数呼び出しには&,リファレンスには\をつけます.

以下のコードとコメントの実行結果を見れば,雰囲気がわかるでしょ?

配列の要素は配列ではなくスカラーであることなどが重要なわけ.

use strict;
use warnings;
use utf8;

$, = " ";                       # print文のセパレータを設定

my $var = 20;
print $var, "\n";               # 20 (スカラー)

my @Arr = (0,1,2,3);
print @Arr, "\n";               # 0 1 2 3 (配列)
print $Arr[2], "\n";            # 2       (配列の要素,要素なのでスカラー)

my %HASH = (name => 'Ken',  country => 'Japan', age => 19);
print %HASH, "\n";              # name Ken country Japan age 19 (ハッシュ)
print $HASH{'name'}, "\n";      # Ken                           (ハッシュの要素,要素なのでスカラー)

print &Hello(), "\n";           # Hello (関数呼び出し)

my $rvar = \$var;
print $rvar, "\n";              # SCALAR(0x6bda48) (スカラーのリファレンス,リファレンスなのでスカラー)
print $$rvar, "\n";             # 20               (スカラーのデリファレンス)
print ${$rvar}, "\n";           # 20               (スカラーのデリファレンス)

my $rArr = \@Arr;
print $rArr, "\n";              # ARRAY(0x6bd9e8) (配列のリファレンス,リファレンスなのでスカラー)
print @$rArr, "\n";             # 0 1 2 3         (配列のリファレンスのデリファレンス,これは配列)
print $$rArr[2], "\n";          # 2               (配列のリファレンスの要素,要素なのでスカラー)
print ${$rArr}[2], "\n";        # 2               (配列のリファレンスの要素,要素なのでスカラー)
print $rArr->[2], "\n";         # 2               (配列のリファレンスの要素,矢印記号なので実体としてスカラー)

my $rHASH = \%HASH;
print $rHASH, "\n";             # HASH(0x6bd8f8)                (ハッシュのリファレンス,リファレンスなのでスカラー)
print %$rHASH, "\n";            # age 19 name Ken country Japan (ハッシュのリファレンスのデリファレンス,これはハッシュ)
print $$rHASH{'name'}, "\n";    # Ken                           (ハッシュのリファレンスの要素,要素なのでスカラー)
print ${$rHASH}{'name'}, "\n";  # Ken                           (ハッシュのリファレンスの要素,要素なのでスカラー)
print $rHASH->{'name'}, "\n";   # Ken                           (ハッシュのリファレンスの要素,矢印記号なので実体としてスカラー)

my $rHello = \&Hello;
print $rHello, "\n";            # CODE(0x6bd580) (関数のリファレンス,リファレンスなのでスカラー)
print &$rHello(), "\n";         # Hello          (関数のリファレンスのデリファレンス,これは関数)
print &{$rHello}(), "\n";       # Hello          (関数のリファレンスのデリファレンス,これは関数)
print $rHello->(), "\n";        # Hello          (関数のリファレンスのデリファレンス,矢印記号なので実体としてスカラー)


sub Hello {
  return "Hello";
}

どうです?

今扱っているデータ構造がわかってエレガントでしょ?

 

さらに言うと,このSigil記法は後述するコンテキストという概念で大きな役割を果たすことになります.

リファレンス

Sigilをみてもわかる通り,Perlはデータ構造をとても重視しています.

先程の例にあったように,変数名の頭に\をつければリファレンスをとれます.

 

皆さんはPythonなどの言語で,次のようなことが起きたことはありませんか?

二次元配列aとそのコピーbがあって,bの要素を書き換えたらなぜかaも変わっていた!!

ってことが.(下のPythonコード参照)

>>> a = [[11,12],[21,22],[31,32]]
>>> a
[[11, 12], [21, 22], [31, 32]]
>>> b = a
>>> b
[[11, 12], [21, 22], [31, 32]]
>>> a[1][0]
21
>>> b[1][0]
21
>>> b[1][0] = 10000
>>> a[1][0]
10000
>>> b[1][0]
10000
>>> a
[[11, 12], [10000, 22], [31, 32]]
>>> b
[[11, 12], [10000, 22], [31, 32]]

初心者あるあるですよね(笑)

学科のPythonの授業で,何度か友人のコードのこれに起因するバグを指摘した記憶があります.

 

上のPythonのコード,データ構造の実装を考えるとちょっとおかしいですよね.

つまり,二次元配列の外側の[]は確かに配列の実体を表していますが,内側の[]は配列の実体ではなく配列の参照を指しているはずなのです.

つまるところ,二次元配列,というのは,「配列の配列」というよりむしろ「配列の参照の一次元配列」が正しいのですが,コードからはそのようなことが見えません.

だから,初心者は上記のようなミスをするわけです.

 

 

データ型に敏感なPerlではこのようなことは起こりません.

Perlではそもそも,多次元配列は配列の参照の配列であることが明確であり,さらには配列と配列の参照(リファレンス)では,そもそもかっこの種類が違います.

配列には()を,配列のリファレンスには[]を使うのです.

 

これによって,多次元配列は配列のリファレンスの配列である,ということが明確になるのです.

use strict;
use warnings;
use utf8;

$, = " ";               # print文のセパレータを設定

my @A = (0, 1, 2, 3);   # 普通の配列
my $B = [0, 1, 2, 3];   # 配列のリファレンス

print @A, "\n";         # 0 1 2 3         (配列)
print $B, "\n";         # ARRAY(0x2d850)  (配列のリファレンス)
print \@A, "\n";        # ARRAY(0x28dfc60)(配列のリファレンス)
print @$B, "\n";        # 0 1 2 3         (配列のリファレンスのデリファレンス)

my @AA = (              # 配列を配列展開しているので,@AAは一次元配列
            (11,12),    # 配列
            (21,22),    # 配列
            (31,32)     # 配列
         );
my @BB = (              # @BBは配列のリファレンスの一次元配列
            [11,12],    # 配列のリファレンス
            [21,22],    # 配列のリファレンス
            [31,32]     # 配列のリファレンス
         );

print @AA, "\n";        # 11 12 21 22 31 32                                  (ただの一次元配列)
print @BB, "\n";        # ARRAY(0x290d838) ARRAY(0x290d778) ARRAY(0x290d718) (配列のリファレンスの一次元配列)

print $AA[1], "\n";       # 12               (一次元配列の要素)
#print $AA[1][1], "\n";   # コンパイルエラー
print $BB[1], "\n";       # ARRAY(0x290d778) (一次元配列の要素)
print $BB[1][1], "\n";    # 22               (二次元配列の要素(配列のリファレンスのデリファレンスでもある))
print ${$BB[1]}[1], "\n"; # 22               (配列のリファレンスのデリファレンス(二次元配列の要素でもある))
print $BB[1]->[1], "\n";  # 22               (配列のリファレンスのデリファレンス(二次元配列の要素でもある))

上のコード,どうですか?

とても論理的です.

 

この仕様のおかげて,Perlのスカラー,配列,ハッシュというデータ構造を自在に組み合わせることができる(つまり,配列のリファレンスのハッシュ,とか,ハッシュのリファレンスの配列のリファレンス,とか)ため,基本的にどのようなデータ構造(オブジェクトでさえ)も実装することが可能になるのです.

 

 

僕はC言語の前にPerlのこのリファレンスを扱っていたため,C言語のポインタでつまずくことはありませんでした.

やっぱ,Perlさいこーだわ....

スカラーコンテキスト,配列コンテキスト

Perlでは,後述する文字列コンテキスト,数値コンテキストなど,コンテキストが重要な意味を持ちます.

 

式が評価される時,それがスカラーなのか配列なのか,で意味が変わってくるのです.

 

さて,下のコードと実行結果を見てください.

use strict;
use warnings;
use utf8;

$, = " ";               # print文のセパレータを設定

my @A = (0, 1, 2, 3);

print @A, "\n";                               # 0 1 2 3 (, は配列コンテキスト.リスト(配列)を返す)
print @A."\n";                                # 4       (. は文字列結合演算子.スカラーコンテキストで働き,スカラーを返す)
print @A == 4 ? "True" : "False", "\n";       # True    (==は比較演算子.スカラーコンテキストで働き,真偽値を返す)

お? って思いますよね?

10行目,なんで4って出力されるの? って.

 

ゆっくり最初から見ていきましょう.

 

7行目で配列@Aを作っています.

 

9行目は,配列@Aprintして改行を出力,って思うでしょ? 正確には違います.

,はカンマ演算子で,左辺がスカラーか配列かによってコンテキストが変化する演算子です.

で今左辺は@Aと配列ですので,これは配列コンテキストでのカンマ演算子,となります.

配列コンテキストでのカンマ演算子の仕様は,「左右辺を持つリスト(配列)を返す」です.

そう,9行目は実は,変数展開をすると,

print (0, 1, 2, 3, "\n");

と評価されていたのです.

 

10行目へ行く前にある事実を.

Perlの配列は,スカラーコンテキストでは要素数を返します!!

 

ってことを頭にいれて10行目へ.

.演算子は,文字列結合演算子であり,スカラーコンテキストです.

したがって,@Aはスカラーとして評価されるので,10行目は

print "4\n";

と評価されていたことになります.

 

ここまでくれば,11行目はもうおわかりでしょう.

比較演算子==はスカラーコンテキストであるので,@Aはスカラーとして,つまり要素数4が返って三項演算子が真となったわけですね.

 

 

他にも

$a = <STDIN>;
@b = <STDIN>;

の1行目ではスカラーコンテキストとなるため,標準入力の一行分が変数$aに代入されます.

一方2行目は配列コンテキストなので,残りの標準入力全ての行が行ごとの配列となって変数@bに代入されます.

 

コンテキストの使い分けはコードが短くスッキリするし,とても便利です.

文字列コンテキスト,数値コンテキスト,不定コンテキスト

スカラーコンテキストはさらに,文字列コンテキスト,数値コンテキスト,不定コンテキストに分けられます.

 

前項では,スカラーのコンテキストか配列のコンテキストかで,結果が変わるということでした.

今回は文字列か数値かで変わるということです.

 

さて,再びPythonを例に上げてみましょうか.

>>> "ab"+"cd"+"ef"
'abcdef'
>>> 1+2+3
6
>>> 1+2+"ef"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>> 1+str(2)+"ef"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>> str(1)+str(2)+"ef"
'12ef'
>>> 1+2+int("ef")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'ef'
>>>

Python,文字列と数値が混在してたらすぐエラー吐く.

文字列をintに変換もエラー吐く.

いちいちstr関数挟むのめんどくさい.

つらい....

 

Perlならば...

use strict;
#use warnings;
use utf8;


print "ab"."cd"."ed" , "\n";     # abcdef
print 1 + 2 + 3      , "\n";     # 6
print "ab"+"cd"+"ed" , "\n";     # 0  (use warnings していると,warningsは出るが,エラーにはならない)
print 1 . 2 . 3      , "\n";     # 123
print "ab"."cd"+"ed" , "\n";     # 0
print "ab"+"cd"."ed" , "\n";     # 0ed

print "10aa"+"9.32vf"  , "\n";   # 19.32
print "10aa"."9.32vf"  , "\n";   # 10aa9.32vf

となります.

+は数値コンテキストでの加算で,.は文字列コンテキストでの結合です.

 

つまり,演算子によってコンテキストが決まり,それによって式の評価が変わるわけです.

この仕様,Perl以外に知らないんだけど,めちゃくちゃ便利だからね.

 

なお,文字列が数値コンテキストによって数値に自動変換されるとき,文字列の頭から数値として解釈できるところまでを切り取って数値にします.(13,14行目参照)

数字から始まらない文字列は,0扱いです.

 

 

加算,結合演算子だけでなく,比較演算子にもコンテキストの使い分けがあります.

比較演算子の等しいは,数値コンテキストでは==,文字列コンテキストではeqですし,

比較演算子の大なりは,数値コンテキストでは>,文字列コンテキストではgtとなります.

(文字列の大小比較がアルファベット順で決まるのは他の言語と一緒.)

省略,特殊変数

Perlにはたくさんの特殊変数があります.

今までのPerlのコードででてきた$,はグローバル特殊変数の一つで,“print演算子が出力フィールドの間に挟み込みセパレータ.デフォルトは空文字列.”です.

$, = " ";

とすることによって,配列をprintするときに空白をセパレータとして設定しているわけです.

 

 

Perlで最頻出の特殊変数は$_@_だと思います.

 

$_はデフォルト操作対象変数で,適当に変数を省略すると$_が使われます.

例えば,下の2組のコードはそれぞれ等価です.

while (<>) {...}       # 標準入力を一行ずつ処理
while ($_ = <>) {...}


/^Subject:/;           # 正規表現によるパターンマッチ
$_ =~ /^Subject:/;


y/a-z/A-Z/;            # 正規表現による置換
$_ =~ y/a-z/A-Z/;


chop;                  # 末端文字除去
chop($_);

 

さらにはforeachなどのループでの要素もこれでアクセスできます.つまり,

foreach my $item (@Items) {
    &hoge($item);
}


foreach (@Items) {
    &hoge($_);
}

も等価.

これはマジで便利.

 

一方,@_は関数(サブルーチン)の引数を格納した配列です.

use strict;
use warnings;
use utf8;

$, = " ";
&hoge("a", "b", "c");

sub hoge {
    print @_, "\n";
    print "0 : ", $_[0], "\n";   # 配列@_の要素はスカラーなので$_[]
    print "1 : ", $_[1], "\n";
    print "2 : ", $_[2], "\n";
}

# 実行結果
# a b c
# 0 :  a
# 1 :  b
# 2 :  c

Perlっておもしろいことに,全ての関数は本質的に可変個の引数をとれるんですよね.

こういうPerlの仕様がPerlの柔軟性を生み出しているわけです.

Perlらしいサンプルコード

ここまで,いくつかのPerlの特徴を見てきたので,実際のPerlらしいコードを見ていきましょうか.

 

■ 項目の出現回数をカウントする

use strict;
use warnings;
use utf8;

my @Data = ("JPN", "USA", "IND", "CHN", "JPN", "JPN", "USA", "IND", "JPN", "RUS", "JPN", "JPN", "IDN", "CHN", "CHN");
my %count;
$count{$_}++ foreach (@Data);           # 後置もできる
foreach (sort keys %count) {            # ハッシュのkey配列をsortしてforをまわす
  printf "%3s : %d\n", $_, $count{$_};
}

# 実行結果
# CHN : 3
# IDN : 1
# IND : 2
# JPN : 6
# RUS : 1
# USA : 2

■ 整数に位取りのカンマを3桁おきに挿入する関数

sub Commas {
  my ($_) = @_;                       # 引数を左辺配列コンテキストでデフォルト特殊変数に渡す
                                      # つまり,可変個の引数のうち第一引数を$_に代入
  1 while s/(.*\d)(\d\d\d)/$1,$2/;    # while節で正規表現による置換.1は何もしない命令.
                                      # 置換に失敗するとwhileから抜ける
  $_;                                 # 返り値
}

 

Perlらしい美しいコードですよね.

4.Perlの文化

Perlには他の言語にはない様々な文化があります.

それは,TMTOWTDIによってもたらされるPerlの柔軟性からきてるのではないでしょうか?

 

ここではそのうちの2つを取り上げます.

コードゴルフ(Perl golf),ワンライナー

皆さんはコードゴルフをご存知ですか?

プログラミングでゴルフをしよう,という頭のおかしい競技のことです.

つまり,出題されたアルゴリズムを最小の文字数(正確にはソースコードのバイト数)で実装した人が勝ち,というもの.

これの発祥はPerlのPerl golfと言われています.

 

一番有名なコードゴルフは,RSA暗号の暗号化を5行で実装したですかね?

そのコードがこちら.

#!/usr/local/bin/perl -s
do 'bigint.pl';($_,$n)=@ARGV;s/^.(..)*$/0$&/;($k=unpack('B*',pack('H*',$_)))=~
s/^0*//;$x=0;$z=$n=~s/./$x=&badd(&bmul($x,16),hex$&)/ge;while(read(STDIN,$_,$w
=((2*$d-1+$z)&~1)/2)){$r=1;$_=substr($_."\0"x$w,$c=0,$w);s/.|\n/$c=&badd(&bmul
($c,256),ord$&)/ge;$_=$k;s/./$r=&bmod(&bmul($r,$r),$x),$&?$r=&bmod(&bmul($r,$c
),$x):0,""/ge;($r,$t)=&bdiv($r,256),$_=pack(C,$t).$_ while$w--+1-2*$d;print}

コードの解説はに載っていますよ.

 

 

コードゴルフと同系列の遊びとして,ワンライナーと言うものもあります.

もともとテキスト処理で盛んに使われていたPerlですので,ワンライナーは日常的に使われていました.

 

たとえばファイルから重複した行を取り除くワンライナー.

perl -ne 'print unless $seen{$_}++' hoge.txt

これくらいならたわい無いんですけど,ワンライナーガチ勢は,もっと複雑な処理すら一行で書いてしまいます....

 

競技プログラミングサイト(コードゴルフサイトではない)に投稿されていたPerlワンライナーを解読してみた記事「」を書きましたので,詳しくはこれを読んでみてください.

 

 

さらに派生して,Perl記号ゴルフと言うものもありますね.

これは,記号しか使ってはいけない,というものです(もはや何がしたいかわからない...).

 

にPerl記号ゴルフでのHello world!の解答とその解説が載っていました.

解答だけ引用すると,

''=~('(?{'.('[[).[|`%,,/`[/[@$'^'+)@@/^(@@@@@,@),@').'!
"})')

となります.

print 'Hello world!'としたいところですが,記号のみしか使えない,つまりアルファベットは使用禁止なので,printHello worldも使えません(笑)

 

解説読んだけど,ただただ「なるほど~」って唸ってるだけでした.

まだまだPerlの修行が足りないようです.

Perlの詩

なんとPerlは詩が書けるプログラミング言語なのです.

1992年には,"Camels and Needles: Computer Poetry Meets the Perl Programming Language" という,Perlの詩に関する論文まででています.

 

に次のような詩がのっていました.

これがコンパイル通るなんて....

#!/usr/bin/perl

APPEAL:

listen (please, please);

open yourself, wide;
    join (you, me),
connect (us,together),

tell me.

do something if distressed;

    @dawn, dance;
    @evening, sing;
    read (books,$poems,stories) until peaceful;
    study if able;

    write me if-you-please;

sort your feelings, reset goals, seek (friends, family, anyone);

        do*not*die (like this)
        if sin abounds;

keys (hidden), open (locks, doors), tell secrets;
do not, I-beg-you, close them, yet.

                            accept (yourself, changes),
                            bind (grief, despair);

require truth, goodness if-you-will, each moment;

select (always), length(of-days)

# listen (a perl poem)
# Sharon Hopkins
# rev. June 19, 1995

 

なお,には "Black Perl" という詩も載っています.

とても過激なのでここには載せませんが,興味のある人はからご覧になってください.

5.終わりに

Perl生誕30周年日ということで,適当にPerlについて書いてみました.

 

ご覧の通り,Perlは素晴らしい言語なので,ためしに使ってみてください.

UNIXコンピュータであれば,デフォルトで入っていますし,WindowsだとしてもActive Perlなどを使えばすぐインストールできますから.

 

Perlのある生活を,ぜひ.

6.出典・参考サイト

Larry Wall and Randal L. Schwartz. Trans. by 近藤 嘉雪. Perlプログラミング. ソフトバンク株式会社出版事業部. 1997.
Tech総研. Perl、C、Scala…プログラミング言語擬人化計画2. Retrieved December 10, 2017, from https://next.rikunabi.com/tech/docs/ct_s03600.jsp?p=002477
Qiita. Perl、Python、PHP、Rubyについて. Retrieved December 10, 2017, from https://qiita.com/raccy/items/81f936e324c4dde61d9f
Wikipedia. Ruby. Retrieved December 10, 2017, from https://ja.wikipedia.org/wiki/Ruby
Qiita. 改めて、CPANいいよね!. Retrieved December 10, 2017, from https://qiita.com/magnolia_k_/items/36d32050a891fca49e76
日経Linux. Linuxをめぐる運動は,とても健康的なものだ Perl言語の開発者,Larry Wall氏インタビュー. Retrieved December 10, 2017, from http://itpro.nikkeibp.co.jp/linux/column/interview/1/index.shtml
Cypherspace. RSA in 5 lines of perl. Retrieved December 10, 2017, from http://www.cypherspace.org/rsa/pureperl.html
兼雑記. Perl 記号ゴルフと Acme::EyeDrops. Retrieved December 10, 2017, from http://shinh.hatenablog.com/entry/20061107/1162835826
Sharon Hopkins, Telos Corporation. CAMELS AND NEEDLES: COMPUTER POETRY MEETS THE PERL PROGRAMMING LANGUAGE. Retrieved December 10, 2017, from http://www.digitalcraft.org/iloveyou/images/Sh.Hopkins_Perl_Poetry.pdf
docstore.mik.ua. 27.2. Perl Poetry. Retrieved December 10, 2017, from https://docstore.mik.ua/orelly/perl/prog3/ch27_02.htm

関連記事

コメントを投稿

名前

Email (※公開されることはありません)

コメント