Perlの哲学 - Perlに対する誤解を解く

WindowsでPerlを使うべきではないというのは本当ですか?

「WindowsでPerlを使うべきではないというのは本当ですか?」

この質問に答えてみましょう。

PerlはWindowsをサポートしている

まず前提知識として、PerlコアはWindowsをサポートしています。

PerlはC言語で書かれていますが、ソースコードを見ると、Windows用のポーティングがあります。

Windows用のディストリビューション

Perlには、Windows用のディストリビューションとして、Active Perl(アクティブパール)とStrawberry Perl(ストロベリーパール)があります。

ディストリビューションというのは、PerlをWindowsでインストールを簡単にして、使いやすくしたものだと考えてください。

Active PerlもStrawberry Perlも、最新版のPerlがリリースすると、その少し後に、リリースされています。

どうしてWindowsでPerlを使うべきではないという人がいるのか

Perlは、Windowsで正しく動き、ディストリビューションも最新版が存在するのに、WindowsでPerlを使うべきではないといった人がいるのはなぜなのでしょう?

それは、日本語の問題です。Windowsでは、日本語が扱いにくいという批判です。

結論を先に書くと、Perlは、Windowsで日本語を正しく扱えますし、正しい作法を覚えれば、不自由することはありません。

でも、そういう批判がでたということは、Perlの日本語処理は、確かに、歴史的に、混乱した時期があったのです。

Perlの日本語処理の混乱とは何か

Webを検索すると、Perlには、さまざまな日本語処理のやり方がでてきます。

jcode.pl、JCode.pm、Encode、encoding、JPerl、binmode、utf8、utf8::is_uft8。

さて、私たちは、いったい何を信用すればよいのでしょうか?

どうして、これほどまでに、Webに存在する日本語処理の方法は、混在しているのでしょうか?

ひとつの理由は、時代の推移にあります。

日本語を正しくサポートしていなかったPerl 4とPerl 5初期

Perl 4とPerl 5の初期は、Unicodeのサポートが存在していません。

ですので、この時代Windowsのcp932(Shift_JISの派生)で、Perlを使おうと思うと、日本語処理が不便でした。

ですので、Perlにcp932の文字コードをそのまま扱えるパッチをあてたJPerlというものが開発されました。

これは、Perl本体にパッチをあてています。つまり、jperlは、Perlそのものではなくって、Perlの派生です。

これとは別に、Perlで日本語処理を扱う方法として、Perlとjcode.plと呼ばれる文字のエンコードモジュールを使う方法も存在しました。

jcode.plをモジュール化したのがJcode.pmです。

Perl 5の後期で、Unicodeをサポートすることによって、Perl本体でも、日本語のようなマルチバイト文字を扱おうという流れになってきました。

Perl 5.6で試験的にUnicdeがサポートされ、Perl 5.8でEncodeが導入されました。Unicode周辺のバグがなくなったのは、Perl 5.8.7です。

これは、2002年~2007年の間です。

日本語処理、大混乱の時期

もちろんUnicodeがサポートされたからといって、以前の習慣があるわけですから、そんなに簡単に、新しい習慣に変えられるはずもありません。

実際、jcode.plやJCode.pmを使っているプログラムを、新しいUnicodeの仕組みにリファクタリングするのは、かなりの労力が必要です。

JPerlの側から見れば、利便性を考えた場合に、Perl 5.8のUnicodeサポートを利用する場合は、ひと手間増えるのは事実でした。

また、新しいUnicodeの仕組みは、内部の文字コードと外部の文字コードを明確に区別するという仕組みでしたから、jcode.plやJCode.pmのエンコーディングの仕組みとは、根本的に概念が異なるのです。

新しいUnicodeの仕組みは、不便で、よくわからないものでした。文字を結合すれば、文字化けするし、Wide Characterの警告を出しまくるし、これは、Perlコアチームの失敗だったと、感じたわけです。

utf8::is_utf8で、Perlが内部の文字コードを使っているか、外部の文字コードを使っているかを判定できると誤解されていた時期もありました。

Perlに詳しい人や、Perlのコミュニティ、CPAN著者でも誤解して使っていました。

大混乱の時期があったわけです。

でも、僕が、Perlや文字コードを学んで2020年から振り返ってみると「Perlの後方互換性を保ちながら、Unicodeを導入するために、これより優れた方法はあったのだろうか?」と感じます。

「どうしたらよかったんだ?」と考えたときに、これより良い方法をなかなか思いつけないのです。

Perlのコアチームは、制約の中で、最善の実装をしたと思います。

単純な解決策は、外に出すときはencode、内にいれるときは、decode

2020年におけるPerlの文字コードの単純で良い方針は、プログラムの外に出すときはEncodeモジュールのencode関数で、実際の文字コードに変換し、decode関数で、内部の文字コードに変換するというものです。

プログラムはUTF-8で保存し、先頭に「use utf8」を記述します。

これだけです。

パフォーマンスや記述の楽さの点で、他の方法も存在しますが、まず、単純で、あらゆるパターンに対応できる、上記の方法を覚えるのがよいでしょう。

詳しくは以下の記事で解説しています。

よくある質問

日本語ファイル名はどのように扱いますか?

open関数に渡すときに、cp932にエンコードします。ファイル名は、プログラムの外側にあります(OSはプログラムの外側)ので、open関数を呼び出す位置で、encodeします。

use utf8;

my $file = 'あああ.txt';

open my $fh, '<', encode('cp932', $file)
  or die "Can't open file: $!";

open以外のファイル名を受け取る関数(unlinkやFile::Copy::copy, File::Copy::move)なども同じです。

あまりにもたくさんある場合は、サブルーチン化すると、少し楽になります。

use utf8;

sub cp932 {
  my ($file) = @_;
  
  $file = encode('cp932', $file);
  
  return $file;
}

my $file = 'あああ.txt';

open my $fh, '<', cp932($file)
  or die "Can't open file: $!";