NAME

version - バージョンオブジェクトのための Perl 拡張

SYNOPSIS

  use version;
  $version = version->new("12.2.1"); # must be quoted for Perl < 5.8.1
  print $version;               # v12.2.1
  print $version->numify;       # 12.002001
  if ( $version gt "12.2" )     # true

  $alphaver = version->new("1.02_03"); # must be quoted!
  print $alphaver;              # 1.02_0300
  print $alphaver->is_alpha();  # true
  
  $ver = qv("1.2.0");           # v1.2.0

  $perlver = version->new(5.005_03); # must not be quoted!
  print $perlver;               # 5.005030

DESCRIPTION

最近の全てのバージョンの Perl 用のオーバーロードされた バージョンオブジェクト。 このモジュールは、Perl 5.10.0 の一部になる予定のバージョンオブジェクトの 全機能を実装しています。

BEST PRACTICES

もしあなたのモジュールを違うバージョンの Perl で使えるようにしたければ、 あるいは $VERSION スカラーがあなたが意図する値を正しく取るようにしたければ、 従うべき単純なルールがいくつかあります:

version.pm を使うモジュールの使い方

可能な限り、version.pm モジュールは既存の全てのコードとの互換性を保ちます。 ただし、もしあなたのモジュールがバージョンクラスを用いて $VERSION を 定義するモジュールを使用している場合、知っておくべきことがいくつか あります。 議論のため、以下のモジュールがインストールされていることを仮定します:

  package Example;
  use version;  $VERSION = qv('1.2.2');
  ...module code here...
  1;
数値バージョンは常に動作する

以下の形式のコード:

  use Example 1.002003;

は常に正しく動作します。 use はモジュール名の次の項として与えられる 浮動小数点 (例:上述の 1.002.003) を使って自動的に $VERSION の比較を 行います。 この例では、インストールされているモジュールは要求されたコードに 対して古すぎるので、次のようなエラーが表示されるでしょう:

  Example version 1.002003 (v1.2.3) required--this is only version 1.002002 (v1.2.2)...
拡張バージョンは時々動作する

Perl >= 5.6.2 では、次のようなコードを使うこともできます:

  use Example 1.2.3;

そしてこれも、たとえ通常は v-文字列 (下記の "What about v-strings" を参照) を サポートしていないバージョンの Perl であっても、正常に動作するでしょう (すなわち、上述のエラーメッセージが表示されます)。 この場合、use は 2 番目の項が 数字のように見える かどうかをチェックし、 それを Replacement UNIVERSAL::VERSIONに渡すだけだという事実が 関わってきます。 しかし、このことは Perl 5.005_04 では正しくなく、そのために extended version をサポートする Perl のバージョンにおいてさえも、コード中では 常に数値バージョンを使うことが 強く推奨 されます。

で、バージョンって何?

このモジュールの用途のため、バージョン「番号」は、1つ以上の小数点と 省略可能な 一つのアンダースコアによって区切られる正の整数値とします。 これは Perl 自身がバージョンを表すのに使用するものに対応し、また ラクダ本の各版で論じられた「数字としてのバージョン」を拡張します。

実際にはバージョンオブジェクトには 2 種類あります。

これらのメソッド両方が同様のバージョンオブジェクトを生成します; なぜなら、必要なときにのみデフォルトの文字列化はバージョンの "Normal Form" を生み出すからです:

  $v  = version->new(1.002);     # 1.002, but compares like 1.2.0
  $v  = version->new(1.002003);  # 1.002003
  $v2 = version->new("1.2.3");   # v1.2.3

特に、"Numeric Versions" として初期化されたバージョン番号は 最初に作られた時のもの (つまり、new() に渡されたのと同じ文字列) で 文字列化します。 "Extended Versions" として初期化されたバージョン番号は "Normal Form" として文字列化されます。

数値バージョン

これらは 5.6.0 より前の Perl 自身の歴史上のバージョンや、$VERSION スカラ用の ラクダルールを踏襲する他のモジュール全てに対応します。 数値バージョンは浮動小数点のように見えるもので初期化されます。 先頭の 0 は 有効で 末尾の 0 は暗黙に仮定されるので、3 点の 最小値は下位バージョン間で保持されます。 これが意味するのは、3 桁より少ない桁数の下位バージョン (小数点より 右の数字) は全て末尾への0の追加によって補われますが、しかしそれは他の バージョンオブジェクトとの比較のためだけです。 例えば:

                                   # Prints     Equivalent to  
  $v = version->new(      1.2);    # 1.2        v1.200.0
  $v = version->new(     1.02);    # 1.02       v1.20.0
  $v = version->new(    1.002);    # 1.002      v1.2.0
  $v = version->new(   1.0023);    # 1.0023     v1.2.300
  $v = version->new(  1.00203);    # 1.00203    v1.2.30
  $v = version->new( 1.002003);    # 1.002003   v1.2.3

入力値がクォートされているかに関わらず、先行例は全て真となります。 重要な特徴として、入力値が一つの小数点を持つことがあります。 扱う方法は "Alpha Versions" も参照してください。

重要な注意:上述で示されているように、数値バージョンが小数点の後に 3 つを 超える有効桁数を含む場合、3 の各倍数で区切られるので 1.0003 は v1.0.300 と 等しくなります。 これは Perl 自身の 5.005_03 == 5.5.30 という解釈との互換性を 維持する必要があるためです。 末尾の 0 は数学的な比較用に全て無視されます。

拡張バージョン

これらは最も新しい形式のバージョンで、5.6.0 から始まる Perl 自身の バージョン形式に対応します。 Perl 5.10.0 からは、またほぼ確実に Perl 6 でも、これが 好まれる形式になりそうです。 このメソッドは通常入力引数がクォートされている必要があり、 また 5.8.1 以降の Perl では v-文字列 をクォートの特別形式として 使用することができますが、これは強く非推奨です。

"Numeric Versions" と違って、拡張バージョンは 2 つ以上の小数点を 持ちます。 例えば:

                                   # Prints
  $v = version->new( "v1.200");    # v1.200.0
  $v = version->new("v1.20.0");    # v1.20.0
  $v = qv("v1.2.3");               # v1.2.3
  $v = qv("1.2.3");                # v1.2.3
  $v = qv("1.20");                 # v1.20.0

一般的に、拡張バージョンは最も高い自由度でバージョンを指定でき、その 一方で数値バージョンは一定の統一性を強制します。 バージョンオブジェクトのもう一つの補助的な初期化メソッドについては "New Operator" も参照してください。

"Numeric Versions" と全く同様に、拡張バージョンは "Alpha Versions" として 使用することができます。

数値αバージョン

かつて数値バージョンが必ずクォートされていなければならなかったのは、 アルファ形式が他の数値バージョン (すなわち小数点が一つ) と一緒に 使われていたときです。 これはよく CPAN リリースに使われており、そこで CPAN や CPANPLUS は自動アップデートのためにアルファバージョンを無視します。 非アルファリリースに小数の有効桁数を2としていた開発者がいたため、 バージョンオブジェクトは初期化子がクォートされていれば自動的に それを考慮します。 例えば、Module::Example が以下の $VERSION 系列で CPAN に リリースされたとします:

  # $VERSION    Stringified
  0.01          0.01
  0.02          0.02
  0.02_01       0.02_01
  0.02_02       0.02_02
  0.03          0.03
  etc.

数値バージョンの文字列化形式は、常にバージョンオブジェクトの初期化に 使われるのと同じ文字列です。

オブジェクトメソッド

バージョンオブジェクトの利用にとって自然なインタフェースを提供するために、 オーバーロードが使われてきました。 数学的な演算は全て、ベースのバージョンオブジェクトに対して意味を 成さないので、禁止されています。 その結果、オーバーロードされた数値化は存在せず利用できません。 もし何らかの理由でバージョンオブジェクトを数値コンテキストで使用したい 場合は、オブジェクトメソッドの numify を参照してください。

以降の例では、以下の 3 つのオブジェクトが使われます:

  $ver   = version->new("1.2.3.4"); # see "Quoting" below
  $alpha = version->new("1.2.3_4"); # see "Alpha versions" below
  $nver  = version->new(1.002);     # see "Numeric Versions" above

クォート

Perl がパースとトークン化を行うプログラムの仕組みのため、意図した バージョンに正しくパースするために、特に qv() 演算子を使用する際には、 特定の初期値は 必ず クォートしなければなりません。 全てのケースにおいて、version->new() に渡される浮動小数点数の値は、その値が クォートされていようとなかろうと同一に変換されます。 しかし、qv() では、クォートされていない入力で末尾のゼロが 抜け落ちてしまう場合にはそのようにならず、全く異なる バージョンオブジェクトが結果として返されます。

加えて、以前の Perl のバージョンスタイルと互換性を保つために、5.006001 と いう形式のバージョンを使用すると全て v5.6.1 のように変換されます。 言い換えると、小数点が 1 つのバージョンは、下位バージョン間には 3 桁の 数字が暗黙的に存在するようにパースされますが、その目的は内部比較のみです。

ややこしくしている要因は、裸の数値 (すなわちクォートされていないもの) では アンダースコアは正当な数値用の文字であって、バージョンコードが 呼び出される前に Perl のトークナイザによって自動的に剥ぎ取られることです。 しかしながら、もし数値が 1 つ以上の小数を含んでいてアンダースコアが クォートされている場合、すなわち裸の数値ではない場合、 "Alpha Version" であると見なされてアンダースコアが有効になります。

もし浮動小数が求まる数式を使った場合、期待するバージョンを生み出せるか どうかは Perl の変換ルーチンに依存することになります。 例えば 10 の累乗で割ることは非常に安全ですが、他の演算はおそらく期待する 値にはならないでしょう。 例えば:

  $VERSION = version->new((qw$Revision: 1.4)[1]/10);
  print $VERSION;          # yields 0.14
  $V2 = version->new(100/9); # Integer overflow in decimal number
  print $V2;               # yields something like 11.111.111.100

Perl 5.8.1 以降はv-文字列を自動的にクォートできますが、それは以前の バージョンの Perl では不可能です。 言い換えれると:

  $version = version->new("v2.5.4");  # legal in all versions of Perl
  $newvers = version->new(v2.5.4);    # legal only in Perl >= 5.8.1

v-文字列はどう?

Perl 5.6.0 以降では、任意のバイト列をコーディングする代替方法が導入され、 v-文字列と呼ばれています。 v-文字列は、例えば (1 文字あたり 2 バイトを使う) Unicode 文字列のようなものを入力するのが簡単なようになっています。 プリンタ制御文字 (すなわち CRLF) をエンコードするためにv-文字列を 使っているプログラムもあります。 v-文字列は $VERSION のために使われるようにも意図されていましたが、 そのような使用は初めから問題をはらんでいました。

v-文字列を入力する方法は 2 つあります。 2 つ以上の小数点を持つ裸の数値か、先頭に裸の文字 'v' があって 1 つ以上の小数点を持つ裸の数値です。 例えば:

  $vs1 = 1.2.3; # encoded as \1\2\3
  $vs2 = v1.2;  # encoded as \1\2 

しかしながら、バージョンオブジェクトを初期化するために裸のv-文字列を 使用することは、実行している Perl が何かに依存して意味が変わるので、 どのような状況であっても 強く 非推奨です (特に先頭に'v' が付く スタイルは)。 "Extended Versions" を直接使って適切な解釈を確実にすることが より良いでしょう。

もし Perl > 5.6.0 で裸のv-文字列を使うことにこだわる場合、以下の制限に 注意してください。

Perl のリリース 5.6.0 から 5.8.0 において、v-文字列コードはv-文字列の いくつかの特徴に基づいて単に推測を行うのみです。 このヒューリスティクスが成功するためには、必ず 3 つの部分 (例えば 1.2.3 や v1.2.3) のバージョンを使わなければ なりません

Perl のリリース 5.8.1 以降では、v-文字列は Perl コアでマジカルになるように 変更されました。 つまり、version.pm コードがv-文字列エンコーディングが使われたかどうかを 自動的に判断できるようになったということです。

3) 全ての場合で、v-文字列を使って作成されたバージョンは 文字列化形式にしたときに先頭に 'v' の文字がつきます; ときどき、これが先頭に付いていたかを確認することが不可能であるという 単純な理由によります。

バージョンオブジェクトの種類

2 種類のバージョンオブジェクトが存在します。

代替 UNIVERSAL::VERSION

バージョンオブジェクトに加えて、このモジュールは比較のためにコアの UNIVERSAL::VERSION 関数をバージョンオブジェクトを使うものに 置き換えることも行います。 この演算子から返されるものは常に文字列化された形式ですが、 生成された警告メッセージは、どのように呼び出されたかに依存して、 文字列化形式か Normal Form のどちらかになります。

例えば:

  package Foo;
  $VERSION = 1.2;

  package Bar;
  $VERSION = "1.3.5"; # works with all Perl's (since it is quoted)

  package main;
  use version;

  print $Foo::VERSION; # prints 1.2

  print $Bar::VERSION; # prints 1.003005

  eval "use foo 10";
  print $@; # prints "foo version 10 required..."
  eval "use foo 1.3.5; # work in Perl 5.6.1 or better
  print $@; # prints "foo version 1.3.5 required..."

  eval "use bar 1.3.6";
  print $@; # prints "bar version 1.3.6 required..."
  eval "use bar 1.004"; # note numeric version
  print $@; # prints "bar version 1.004 required..."

重要な注意: (与えられたモジュールが利用可能かどうかを決定するために) 特定の文字列を検索するためのコードは変更が必要かもしれないことを 意味します。 手動で class-VERSION> を使ってから自分で比較を行うより、 userequire で暗黙に使われる組み込みの比較を使う方が 常に優れています。

UNIVERSAL::VERSION の代替物は、以下のように関数として使われた際:

  print $module->VERSION;

これも文字列化形式のみを返します。 更なる詳細については Stringification を参照してください。

サブクラス化

このモジュールは簡単にサブクラス化ができるように明確に設計やテストがさ れています。 実際には、変更したいメソッドをオーバーライドするだけで OK ですが、 new() をオーバーライドする際には注意が必要です (パースが全て行われる 場所なので)。 例えば、これは完全に条件を満たしている派生クラスです:

  package myversion;
  use base version;
  sub new { 
      my($self,$n)=@_;
      my $obj;
      # perform any special input handling here
      $obj = $self->SUPER::new($n);
      # and/or add additional hash elements here
      return $obj;
  }

バージョン文字列の代替の表現形式については CPAN の version::AlphaBeta も 参照してください。

注意: qv 演算子は真のクラスメソッドではなく、むしろ呼び出し元の 名前空間にエクスポートされた関数で、version のサブクラスは、その サブクラスに代わって正しいマジックを実行する import() 関数を継承します。

EXPORT

qv - 拡張バージョン初期化演算子

AUTHOR

John Peacock <jpeacock@cpan.org>

SEE ALSO

perl.