[perl]Readonlyやめてdlockにします。

Written by uechoco 4月 14
[perl]Readonlyやめてdlockにします。 はコメントを受け付けていません。
この記事を読む時間:51くらい

最近はphpを触ってもいなくて、もっぱらPerlしか触っていないうえちょこです。

Perlは初心者(と言い続けるのもアレなんですが。。。)なので、まだまだプログラムの”イイ形“を見つけている最中です。今回は定数の定義方法についてのお話です。私はReadonly派だったのですが、後述の記事でReadonlyの弱点を知ったので、本格的にdlock関数に乗り移ろうと決めました。

Perlの定数定義(constant編)

本題に入る前に、王道から学んでいきます。perlの標準的な定数の定義方法は、constantモジュールを使用して

  1. use constant FLAG_ON => 1;

といったように記述します。ただこの方法には面倒な問題がいくつもあって、この定数は定数もどきで実は単なる関数だったりします。定数なので上書きしようとするとコンパイルエラーが通るのは素晴らしいのですが、関数なので文字列内で展開できなかったりハッシュや配列がリファレンスでないと定義できなかったりします。

Perlの定数定義(Readonly編)

とまぁConstantモジュールには使いづらい点が幾つもあったわけですが、そんなことは全く知らずに、私はReadonlyモジュールという方を使用していました。Readonlyモジュールで定数を定義する場合は

  1. use Readonly;
  2. Readonly my $FLAG_ON => 1;

というように記述します。Readonlyモジュールを使用すれば配列やハッシュも普通に定義できますし、文字列内で展開もできます。ちょっとやっかいなのは、定数を上書きしようとする場合はコンパイル時ではなく実行時にしか検出できないという点です。これは慣れればいいですし、エラーが出ることには変わりないので我慢します。

ですが、もう1つReadonlyには欠点がありました。

Readonlyの欠点

Perlにおける定数宣言(constant or Readonly or Attribute::Constant) – Unknown::Programmingという記事に詳しくまとまっていますが、Readonlyはとにかく遅いようです。記事の末尾にベンチマークが貼ってありますので見てみると、明らかにReadonlyだけが遅いです。

Readonlyが何故遅いのかというと、tieを使用しているからだそうです。tieというのは変数を内部的にオブジェクトに結びつけるperlの仕組みです。Dan先生がだいぶ前にブログ記事にしているのを見つけたので、そちらを参照してください。(404 Blog Not Found:perl – tie()って何をtieするの?

Data::Lock dlockという選択肢

Readonlyは遅いし、constantは使いづらいわけですが、もう1つ定数系モジュールがあります。Attribute::Constantとそのコア部分であるData::Lockです。Data::Lockにはdlockとdunlockという関数が含まれていて、変数をロックすなわち上書きできないようにしてしまうものと、そのロックを解除してしまうものです。定数なのに定数じゃなくせるというのが気持ち悪いという気持ちはありますが、規約でdunlockは使っちゃダメとか決めておけば大した問題にはなりません。

dlockはtieを使っていないのでReadonlyよりも速いですし、使い勝手はReadonlyみたいなものです。詳しくは前述のブログ記事を見てみてください。またdlockについては作者であるDan先生の記事を参照してください(404 Blog Not Found:perl – Attribute::Constant – Another Way to Make Read-only Variables)。

実際のところ

仕事で書いているコードはいろんな人がメンテナンスをしていますが、比較的最近書かれたコードはdlockを使用していることが多いです。ただ、スカラー変数にだけdlockを使用していて配列やハッシュにはReadonlyを使用している箇所が結構ありました。私はそれらのコードを読んで学習しているため、てっきりdlockはスカラー変数だけしか使用できないものかと勘違いしていたのですが、全然そんなことはなく、Readonlyと同等のことができてReadonlyよりも速いモジュールという認識でよさそうです(というところが気になったのでdlockの仕様を調べていたのがこの記事を書くきっかけでした)。

ではでは。