=encoding euc-jp =head1 NAME perltrap - Perlの不注意による罠 =head1 DESCRIPTION =begin original The biggest trap of all is forgetting to C or use the B<-w> switch; see L and L. The second biggest trap is not making your entire program runnable under C. The third biggest trap is not reading the list of changes in this version of Perl; see L. =end original 最も大きな罠とは、C あるいは B<-w> スイッチを 使うのを忘れてしまうということです。 L と L を参照してください。 二番目に大きな罠とは、あなたのプログラム全体を C の元で実行しないということです。 三番目の罠は、Perl のこのバージョンでの変更点を読まないということです。 L を参照してください。 =head2 Awk Traps (awk の罠) B に慣れた方は、以下のようなことに特に注意してください: =over 4 =item * Englishモジュールを use English; のようにしてロードすれば、B でそうであったように (C<$/> のような)特殊変数を($RS のような)名前で参照することができます。 詳しくは L を参照してください。 =item * Perlでは、すべての単純文(simple statement)の末尾にセミコロンが必要です (ブロックの最後に置かれたときを除きます)。 改行は文の区切りとはなりません。 =item * C や C ではカーリーブレースが必要です。 =item * Perlでは、変数は“$”"か“@”か“%”で始まります。 =item * 配列の添え字は 0 から始まります。substr() や index() での文字列の位置も 同様です。 =item * 配列の添え字が数値であるか、文字列であるかを決めなければなりません。 =item * ハッシュ(連想配列)の値は、単に参照するだけでは存在することに なりません。 =item * 比較を文字列によって行うのか、数値によって行うのかを 決めなければなりません。 =item * 入力を読み込むだけでは split は行われません。 配列への split は自分で行います。 また、split() 演算子の引数は B のものと異なっています。 =item * 通常、カレント行は $0 ではなく $_ にあります。 一般的に、改行は取り除かれません ($0 には実行しているプログラムの名前があります)。 L を参照してください。 =item * $> はフィールドを参照しません。これは 直前に行ったパターンマッチングの部分文字列を参照します。 =item * print() 文は、C<$,> や C<$\> に値を設定しない限りフィールド区切り子や レコード区切り子を付加しません。English モジュールを使っていれば、 $OFS や $ORS に対して設定することでも OK です。 =item * ファイルに対して出力する前には、そのファイルをあらかじめオープンして おかなければなりません。 =item * 範囲演算子は“..”であって、カンマではありません。カンマ演算子は Cと同じような振る舞いをします。 =item * マッチ演算子は“=~”であって、“~”ではありません (“~”はCと同様に、1の補数を取る演算子です)。 =item * べき乗の演算子は“**”であって、“^”ではありません。 “^”はCと同様、XOR演算子です (B が基本的に C と非互換であることにお気付きかもしれませんね)。 =item * 連接演算子は“.”であって、空文字列ではありません (空文字列を使ってしまうと C が、その三番目のスラッシュが除算演算子と解釈されてしまうので 正しく解析できなくなります。 Perl の字句解析器は "/", "?", ">" といった演算子に対して 多少文脈依存となっています。実際、"." 自身も数値の始まりとなる 可能性もあります) =item * キーワード C, C, C の振る舞いが異なります。 =item * 以下の変数の働きが異なります。 Awk Perl ARGC scalar @ARGV (compare with $#ARGV) ARGV[0] $0 FILENAME $ARGV FNR $. - something FS (whatever you like) NF $#Fld, or some such NR $. OFMT $# OFS $, ORS $\ RLENGTH length($&) RS $/ RSTART length($`) SUBSEP $; =item * $RS に正規表現をセットすることはできません。できるのは文字列だけです。 =item * 妙だと思ったときには awk の構文を a2p に通して、 出力されたものを見てみましょう。 =back =head2 C Traps (C の罠) =begin original Cerebral C programmers should take note of the following: =end original 知的な C プログラマは以下のことに注意すべきです: =over 4 =item * C や C にはカーリーブレースが必要です。 =item * C ではなく、C を使わなければなりません。 =item * C のC と C は、Perlではそれぞれ C と C となります。 C とは異なり、これらは C 構文では I<使えません>。 =item * switch 文はありません(が、その場(on the fly)で作り上げることは簡単です)。 =item * Perl では、変数は“$”か“@”か“%”で始まります。 =item * コメントの始まりは、“#”であり、“/*”ではありません。 =item * なにかのアドレスを得ることはできません。Perl には似たような演算子である バックスラッシュがありますが、これは参照を生成します。 =item * C は大文字でなければなりません。C<$ARGV[0]> が C での C に相当し、 C にあたるものは C<$0> です。 =item * =begin original System calls such as link(), unlink(), rename(), etc. return nonzero for success, not 0. (system(), however, returns zero for success.) =end original link(), unlink(), rename() などのシステムコールは、成功時に 0 ではなく非 0 の値を返します。(但し、system() は成功時に 0 を返します。) =item * シグナルハンドラは、シグナル番号ではなくシグナル名を扱います。 使用できるシグナル名は、kill -l として確かめてください。 =back =head2 Sed Traps (sed の罠) =begin original Seasoned B programmers should take note of the following: =end original 熟練した B プログラマは以下のことに注意すべきです: =over 4 =item * 置換における後方参照には、“\”ではなく“$”を使います。 =item * "(", ")", "|" といったパターンマッチのメタキャラクタは、その直前に バックスラッシュを置く必要はありません。 =item * 範囲演算子は C<...> であって、カンマではありません。 =back =head2 Shell Traps (shell の罠) =begin original Sharp shell programmers should take note of the following: =end original 鋭いシェルプログラマは以下のことに注意すべきです: =over 4 =item * バッククォート演算子は、コマンド内にシングルクォートがあっても 変数の展開を行ないます。 =item * バッククォート演算子は B とは違って、返された値を変換しません。 =item * シェル (特に B) は、コマンドラインごとに何段階もの置換を行ないます。 Perl はダブルクォート、バッククォート、 アングルブラケット、検索パターンといった特定の構造でだけ置換を行ないます。 =item * シェルは一度に少しずつ解釈を行ないます。 Perl は実行前にプログラム全体をコンパイルします (コンパイル時に実行される C ブロックを除く)。 =item * 引数は $1, $2 などではなく、@ARGV から得られます。 =item * 環境変数は、自動的には独立したスカラー変数として利用できるように なりません。 =back =head2 Perl Traps (Perl の罠) =begin original Practicing Perl Programmers should take note of the following: =end original 実践的な Perl プログラマは以下のことに注意すべきです: =over 4 =item * 多くの演算子がリストコンテキストとスカラーコンテキストとで 振る舞いが変わることを忘れないでください。 詳しくは L を参照してください。 =item * 裸の単語、特に全てが小文字のものはできる限り使わないでください。 見た目だけではその「裸の単語」が関数なのか、 文字列なのかが判断できません。文字列にはクォートを、 関数呼び出しには括弧をつければ、迷うこともないでしょう。 =item * =begin original You cannot discern from mere inspection which builtins are unary operators (like chop() and chdir()) and which are list operators (like print() and unlink()). (Unless prototyped, user-defined subroutines can B be list operators, never unary ones.) See L and L. =end original 組込み関数のどれが(chop() や chdir())のような単項演算子で、 どれが(print() や unlink())のような リスト演算子であるかは見ただけではわかりません (プロトタイプがなければ、ユーザー定義サブルーチンは リスト演算子として B<のみ> 定義でき、単項演算子にはできません)。 L と L を参照してください。 =item * いくつかの関数が $_ や @ARGV などをデフォルトにしていますが、 同じことを期待する他の関数がデフォルトになっていないことを覚えるのに、 辛いタイピングが必要でしょう。 =item * 構造はファイルハンドルではなく、そのハンドルに対する行読み込みの 操作(readline operation)です。 while ループの条件式の中にこのファイル読み込みだけがあった場合には 読み込まれたデータは $_ に代入されます。 while () { } while (defined($_ = )) { }.. ; # データは捨てられる! =item * C<=~> が必要なところで c<=> を使わない、ということを忘れないでください。 これら二つの構造はかなり違います。 $x = /foo/; $x =~ /foo/; =item * C 構造は、ループ制御を行えるような本当のループではありません。 =item * ローカル変数は、my() で済むところではこれで済ませること (使えない場所については、L を参照してください)。 local() を使えばグローバル変数に対するローカルな値を与えますが、 動的スコープの不慮の副作用の可能性は、そのままです。 =item * モジュールにある export された変数を局所化すると、その export された 値は変更されません。 ローカル名は新しい値の別名(alias)となりますが、 外部名は元々の値の別名のままです。 =back =head2 Perl4 to Perl5 Traps (Perl4 から Perl5 への罠) =begin original Practicing Perl4 Programmers should take note of the following Perl4-to-Perl5 specific traps. =end original 実践的な Perl4 プログラマは 以下に挙げる Perl4 と Perl5 の違いに特有な罠に気をつけた 方が良いでしょう。 以下は順不同のリストです。 =over 4 =item Discontinuance, Deprecation, and BugFix traps 修正された perl4 のバグや、なくなった perl4 の仕様、 perl5 で仕様の変わったもの。 =item 構文解析に関する罠 新しい構文解析器によって引き起こされるもの。 =item 数値に関する罠 =begin original Traps having to do with numerical or mathematical operators. =end original 数値や算術演算子に関する罠。 =item General data type traps perlの標準的なデータ型に内包される罠。 =item Context Traps - scalar, list contexts リスト内のコンテキストや、スカラー文/宣言に関する罠。 =item 優先順位の罠 構文解析、評価、コードの実行の優先順に関係した罠。 =item General Regular Expression Traps using s///, etc. パターンマッチングの仕様に関する罠。 =item Subroutine, Signal, Sorting Traps シグナル及びシグナルハンドラ、一般的なサブルーチン、ソート、 ソートのためのサブルーチンに関連した罠。 =item OS Traps OS特有の罠。 =item DBM Traps C の使用や、dbm の実装に関連した罠。 =item Unclassified Traps その他の罠。 =back =begin original If you find an example of a conversion trap that is not listed here, please submit it to > for inclusion. Also note that at least some of these can be caught with the C pragma or the B<-w> switch. =end original もしここで挙げたリストにはないような変換の罠の 例を見つけたら、それを > まで送ってください。 また、少なくともこれらのいくつかは C プラグマか B<-w> スイッチで捕捉できることに注意してください。 =head2 Discontinuance, Deprecation, and BugFix traps perl4 から、なくなったり修正されたことがら。 =over 4 =item * Discontinuance “_”で始まるシンボルはもはや main パッケージに強制的に結び付けられることは、 C<$_> 自身(と C<@-> など)を除いてはなくなりました。 package test; $_legacy = 1; package main; print "\$_legacy is ",$_legacy,"\n"; # perl4 の出力: $_legacy is 1 # perl5 の出力: $_legacy is =item * Deprecation ダブルコロンは、変数名の中でパッケージセパレーターになるようになりました。 このため、以下の例では perl4 と perl5 とでは振る舞いが変わります。 これはパッケージが実在してないためです。 $a=1;$b=2;$c=3;$var=4; print "$a::$b::$c "; print "$var::abc::xyz\n"; # perl4 の出力: 1::2::3 4::abc::xyz # perl5 出力: 3 C<::> は今では、(これがバグとして分類すべきかどうかはともかく) パッケージデリミタとしてみなされるようになっています (ここでは古いパッケージデリミタの ' を使っています)。 $x = 10 ; print "x=${'x}\n" ; # perl4 の出力: x=10 # perl5 の出力: Can't find string terminator "'" anywhere before EOF =begin original You can avoid this problem, and remain compatible with perl4, if you always explicitly include the package name: =end original 常にパッケージ名を含めることで、この問題を避けつつ、perl4 との 互換性を維持することができます: $x = 10 ; print "x=${main'x}\n" ; C<$:> の解析については、優先順位の罠 も参照してください。 =item * BugFix C の第 2、第 3 引数は (ラクダ本にある通り)リストコンテキストではなく スカラーコンテキストで評価されるようになりました。 sub sub1{return(0,2) } # 要素二つのリストを返す sub sub2{ return(1,2,3)} # 要素三つのリストを返す @a1 = ("a","b","c","d","e"); @a2 = splice(@a1,&sub1,&sub2); print join(' ',@a2),"\n"; # perl4 の出力: a b # perl5 の出力: c d e =item * Discontinuance 最適化によってなくなってしまうようなブロックの中に 飛び込むC は使えなくなりました。ちぇっ。 goto marker1; for(1){ marker1: print "Here I is!\n"; } # perl4 prints: Here I is! # perl5 errors: Can't "goto" into the middle of a foreach loop =item * Discontinuance 空白を変数の名前や、クォート構造の区切りに使うことは 構文的に正当なものではなくなりました。ちぇっ、ちぇっ。 $a = ("foo bar"); $b = q baz ; print "a is $a, b is $b\n"; # perl4 の出力: a is foo bar, b is baz # perl5 errors: Bareword found where operator expected =item * Discontinuance 古い while/if BLOCK BLOCK の構文は、もはやサポートされていません。 if { 1 } { print "True!"; } else { print "False!"; } # perl4 の出力: True! # perl5 errors: syntax error at test.pl line 1, near "if {" =item * BugFix C<**> 演算子の優先順位は、単項のマイナスよりも高くなりました。 これは以前からドキュメントにはそうあったのですが、実際は違っていました。 print -4**2,"\n"; # perl4 の出力: 16 # perl5 の出力: -16 =item * Discontinuance 配列ではないリストに対する繰り返しで あるときの C の意味が変わりました。 以前はそういったリストはテンポラリな配列に代入されていましたが、 現在はそうではありません(効率上の理由です)。 これは、現在では値のコピーに対して繰り返しをするのではなく 実際の値に対して繰り返しをするということです。 @list = ('ab','abc','bcd','def'); foreach $var (grep(/ab/,@list)){ $var = 1; } print (join(':',@list)); # perl4 の出力: ab:abc:bcd:def # perl5 の出力: 1:1:bcd:def perl4 と同じようにするには、自分で陽にテンポラリの配列へと コピーしてからその配列に対して繰り返しを行います。例えば、 foreach $var (grep(/ab/,@list)){ この部分を以下のように変更します。 foreach $var (@tmp = grep(/ab/,@list)){ そうしないと、$var を変更したときに @list の値に影響が出ます (これはループ変数に C<$_> を使っていて、かつ、 C<$_> を局所化していないようなサブルーチンを ループの中で呼ぶようなときに良く起こります)。 =item * Discontinuance 引数なしの C の振る舞いは、C ($_ が空白から始まっているときに先頭のフィールドが空になる) のときと同じというものから、C ($_ が空白から始まっているときに先頭のフィールドが空にならない) のときと同じものになりました。 $_ = ' hi mom'; print join(':', split); # perl4 の出力: :hi:mom # perl5 の出力: hi:mom =item * BugFix perl4 では、B<-e> スイッチにアタッチされたテキストは無視されて、常に 後に続く引数からプログラムが取り出されていました。さらに、 B<-e> スイッチの後に引数を渡さない場合も受け付けていました。 これらの振る舞いは両方とも修正されました。 perl -e'print "attached to -e"' 'print "separate arg"' # perl4 の出力: separate arg # perl5 の出力: attached to -e perl -e # perl4 prints: # perl5 dies: No code specified for -e. =item * Discontinuance perl4 では C の戻り値はドキュメントに書かれていませんでしたが、 実際には対象となるリストに最後にpushした値が返されていました。 Perl5 では、C の戻り値はドキュメントに明記され、かつそれは perl4 から変更されました。これは push した後のリストにある要素の数を 返します。 @x = ('existing'); print push(@x, 'first new', 'second new'); # perl4 の出力: second new # perl5 の出力: 3 =item * Deprecation 一部のエラーメッセージが異なっています。 =item * Discontinuance =begin original In Perl 4, if in list context the delimiters to the first argument of C were C, the result would be placed in C<@_> as well as being returned. Perl 5 has more respect for your subroutine arguments. =end original Perl 4 では、リストコンテキストで C の最初の引数の デリミタが C だった場合、返される結果が C<@_> にも設定されました。 Perl 5 ではサブルーチンの引数により多くの敬意を払います。 =item * Discontinuance 幾つかのバグがうかつにも修正されているかもしれません :-) =back =head2 Parsing Traps (パースの罠) =begin original Perl4-to-Perl5 traps from having to do with parsing. =end original パースに関する Perl4 と Perl5 の違いの罠です。 =over 4 =item * Parsing . と = の間にあるスペースに注意。 $string . = "more string"; print $string; # perl4 の出力: more string # perl5 の出力: syntax error at - line 1, near ". =" =item * Parsing perl5 では構文解析が改良されました。 sub foo {} &foo print("hello, world\n"); # perl4 の出力: hello, world # perl5 の出力: syntax error =item * Parsing “それが関数に見えるのなら、それは関数だ”のルール。 print ($foo == 1) ? "is one\n" : "is zero\n"; # perl4 の出力: is zero # perl5 の警告: "Useless use of a constant in void context" if using -w =item * Parsing C<$#array> 構造の文字列展開で名前の周りにブレースがあるときには 違いがあります。 @a = (1..3); print "${#a}"; # perl4 prints: 2 # perl5 fails with syntax error @ = (1..3); print "$#{a}"; # perl4 prints: {a} # perl5 prints: 2 =back =head2 Numerical Traps (数値の罠) =begin original Perl4-to-Perl5 traps having to do with numerical operators, operands, or output from same. =end original 同じものに対する数値演算子、オペランド、出力に関する Perl4 と Perl5 の違いの罠です。 =over 5 =item * Numerical =begin original Formatted output and significant digits =end original 書式指定された出力と、最下位の数字。 print 7.373504 - 0, "\n"; printf "%20.18f\n", 7.373504 - 0; # Perl4 の出力: 7.375039999999996141 7.37503999999999614 # Perl5 の出力: 7.373504 7.37503999999999614 =item * Numerical ここに記述されていた項目は削除されました。 以前あったものでは、オートインクリメント演算子が符号付き整数の限界を越えたことを 検知しないということを紹介していました。 これはバージョン 5.003_04 で修正されましたが、大きな整数を取り扱うことに 不安を感じているのであれば use Math::BigInt; を使うことを考慮してください。 =item * Numerical 数値の等価性の比較の結果を代入しても、perl ではその比較の結果が 偽 (0) であったときにはうまくいきません。 論理比較は、現在 0 ではなく null を返します。 $p = ($test == 1); print $p,"\n"; # perl4 の出力: 0 # perl5 出力: この新しい仕様の別の例は L<"General Regular Expression Traps using s///, etc."> を参照してください。 =item * Bitwise string ops =begin original When bitwise operators which can operate upon either numbers or strings (C<& | ^ ~>) are given only strings as arguments, perl4 would treat the operands as bitstrings so long as the program contained a call to the C function. perl5 treats the string operands as bitstrings. (See L for more details.) =end original 数値としても文字列としても操作可能なビット操作演算子 (C<& | ^ ~>) が 文字列のみを引数として与えられた場合、 perl4 は、プログラムが C 関数の呼び出しを含んでいればオペランドを ビット文字列として扱います。 perl5 は文字列オペランドをビット文字列として扱います (さらなる詳細については L を参照してください)。 $fred = "10"; $barney = "12"; $betty = $fred & $barney; print "$betty\n"; # Uncomment the next line to change perl4's behavior # ($dummy) = vec("dummy", 0, 0); # Perl4 prints: 8 # Perl5 prints: 10 # If vec() is used anywhere in the program, both print: 10 =back =head2 General data type traps (一般的なデータ型の罠) =begin original Perl4-to-Perl5 traps involving most data-types, and their usage within certain expressions and/or context. =end original ほとんどのデータ型と、それらの特定の表現やコンテキストでの 使い方に関する Perl4 と Perl5 の違いの罠です。 =over 5 =item * (配列) =begin original Negative array subscripts now count from the end of the array. =end original 配列の添え字が負であったとき、それは配列の終端から数えられるように なりました。 @a = (1, 2, 3, 4, 5); print "The third element of the array is $a[3] also expressed as $a[-2] \n"; # perl4 の出力: The third element of the array is 4 also expressed as # perl5 の出力: The third element of the array is 4 also expressed as 4 =item * (配列) C<$#array> に(それまでよりも)小さな値を設定したときには、余計な 配列要素は捨てられ、さらにそれが元に戻せないようになりました。 @a = (a,b,c,d,e); print "Before: ",join('',@a); $#a =1; print ", After: ",join('',@a); $#a =3; print ", Recovered: ",join('',@a),"\n"; # perl4 の出力: Before: abcde, After: ab, Recovered: abcd # perl5 の出力: Before: abcde, After: ab, Recovered: ab =item * (ハッシュ) ハッシュは使われる前に定義されます。 local($s,@a,%h); die "scalar \$s defined" if defined($s); die "array \@a defined" if defined(@a); die "hash \%h defined" if defined(%h); # perl4 の出力: # perl5 dies: hash %h defined =begin original Perl will now generate a warning when it sees defined(@a) and defined(%h). =end original Perl は defined(@a) と defined(%h) に警告を出すようになりました。 =item * (グロブ) ある変数から別の変数へのグロブの代入は、 代入された変数が代入の後で局所化されているときには 失敗します。 @a = ("This is Perl 4"); *b = *a; local(@a); print @b,"\n"; # perl4 の出力: This is Perl 4 # perl5 の出力: =item * (グロブ) =begin original Assigning C to a glob has no effect in Perl 5. In Perl 4 it undefines the associated scalar (but may have other side effects including SEGVs). Perl 5 will also warn if C is assigned to a typeglob. (Note that assigning C to a typeglob is different than calling the C function on a typeglob (C), which has quite a few effects. =end original C のグロブへの代入は Perl5 では何の影響も及ぼしません。 Perl4 では結び付けられたスカラーを undefine します (しかし SEGV を含め、なんらかの副作用があるかもしれません)。 Perl 5 はまた型グロブに C を代入すると警告されます。 (型グロブに C を代入するのは、型グロブに対して C 関数を呼び出すのとは違います)。いくつかの効果があります。 $foo = "bar"; *foo = undef; print $foo; # perl4 prints: # perl4 warns: "Use of uninitialized variable" if using -w # perl5 prints: bar # perl5 warns: "Undefined value assigned to typeglob" if using -w =item * (スカラー文字列) (文字列に対する)単項の符号反転の意味が変わりました。 この変更は戻り値と、マジックインクリメントの両方に影響します。 $x = "aaa"; print ++$x," : "; print -$x," : "; print ++$x,"\n"; # perl4 の出力: aab : -0 : 1 # perl5 の出力: aab : -aab : aac =item * (定数) perl4 では定数を変更してしまいます。 $foo = "x"; &mod($foo); for ($x = 0; $x < 3; $x++) { &mod("a"); } sub mod { print "before: $_[0]"; $_[0] = "m"; print " after: $_[0]\n"; } # perl4: # before: x after: m # before: a after: m # before: m after: m # before: m after: m # Perl5: # before: x after: m # Modification of a read-only value attempted at foo.pl line 12. # before: a =item * (スカラー) perl4 と perl5 とで全然違う動作: print "$x", defined $x # perl 4: 1 # perl 5: =item * (変数の自殺) perl5 では、変数の自殺(variable sucide)の振る舞いはより 首尾一貫したものとなりました。 perl4 ではスカラーのみがそうであるような振る舞いを、 perl5 ではハッシュとスカラーで示します。 $aGlobal{ "aKey" } = "global value"; print "MAIN:", $aGlobal{"aKey"}, "\n"; $GlobalLevel = 0; &test( *aGlobal ); sub test { local( *theArgument ) = @_; local( %aNewLocal ); # perl 4 != 5.001l,m $aNewLocal{"aKey"} = "this should never appear"; print "SUB: ", $theArgument{"aKey"}, "\n"; $aNewLocal{"aKey"} = "level $GlobalLevel"; # 出力すべきもの $GlobalLevel++; if( $GlobalLevel<4 ) { &test( *aNewLocal ); } } # Perl4: # MAIN:global value # SUB: global value # SUB: level 0 # SUB: level 1 # SUB: level 2 # Perl5: # MAIN:global value # SUB: global value # SUB: this should never appear # SUB: this should never appear # SUB: this should never appear =back =head2 Context Traps - scalar, list contexts (コンテキストの罠 - スカラーコンテキストとリストコンテキスト) =over 5 =item * (リストコンテキスト) =begin original The elements of argument lists for formats are now evaluated in list context. This means you can interpolate list values now. =end original formatに対する引数リストの要素は、リストコンテキストで 評価されるようになりました。これは、今やリストの値が 展開できるようになったということです。 @fmt = ("foo","bar","baz"); format STDOUT= @<<<<< @||||| @>>>>> @fmt; . write; # perl4 errors: Please use commas to separate fields in file # perl5 の出力: foo bar baz =item * (スカラーコンテキスト) C 関数は呼び出し元がなく、スカラーコンテキストで呼ばれた 場合には偽を返すようになりました。これによりライブラリファイルが (自分が)require されたのかを判断することができます。 caller() ? (print "You rang?\n") : (print "Got a 0\n"); # perl4 errors: There is no caller # perl5 の出力: Got a 0 =item * (スカラーコンテキスト) スカラーコンテキストにあるカンマ演算子は、その引数に対して スカラーコンテキストを与えるようになりました。 @y= ('a','b','c'); $x = (1, 2, @y); print "x = $x\n"; # Perl4 prints: x = c # Thinks list context interpolates list # Perl5 prints: x = 3 # Knows scalar uses length of list =item * (list, builtin) =begin original C is prototyped as ($;@), so its first argument is given scalar context. Thus, if passed an array, it will probably not do what you want, unlike Perl 4: =end original C のプロトタイプは ($;@) なので、最初の引数は スカラコンテキストです。従って、配列を渡すと、 Perl 4 とは違っておそらくあなたの望まない結果になるでしょう。 @z = ('%s%s', 'foo', 'bar'); $x = sprintf(@z); print $x; # perl4 prints: foobar # perl5 prints: 3 =begin original C works the same as it did in Perl 4, though: =end original しかし、C のほうは Perl 4 と同じように動きます: @z = ('%s%s', 'foo', 'bar'); printf STDOUT (@z); # perl4 の出力: foobar # perl5 の出力: foobar =back =head2 Precedence Traps (評価順序の罠) =begin original Perl4-to-Perl5 traps involving precedence order. =end original 評価順序に関する Perl4 と Perl5 の違いの罠です。 =begin original Perl 4 has almost the same precedence rules as Perl 5 for the operators that they both have. Perl 4 however, seems to have had some inconsistencies that made the behavior differ from what was documented. =end original Perl4 はほとんどの演算子で Perl5 と同じ優先順位を持っています。 しかし Perl4 では、ドキュメントとは少々異なるような 一貫性に欠けるものがあります。 =over 5 =item * Precedence =begin original LHS vs. RHS when both sides are getting an op. =end original 左辺と右辺は両方とも演算子を取るようになりました。 @arr = ( 'left', 'right' ); $a{shift @arr} = shift @arr; print join( ' ', keys %a ); # perl4 の出力: left # perl5 の出力: right =item * Precedence 以下の例は、優先順位の関係で意味エラー(semantic error)となるようになりました。 @list = (1,2,3,4,5); %map = ("a",1,"b",2,"c",3,"d",4); $n = shift @list + 2; # リストの最初の要素に2を加える print "n is $n, "; $m = keys %map + 2; # ハッシュにあるアイテムの数+2 print "m is $m\n"; # perl4 出力: n is 3, m is 6 # perl5 errors and fails to compile =item * Precedence 代入演算子の優先順位は、代入と同じとなりました。 perl4 は間違って、この優先順位が関連演算子と同じものに なっています。このため、式の中にあるのと同じように括弧でくくらなければ ならなくなりました。 /foo/ ? ($a += 2) : ($a -= 2); 下のようにしてしまうと、 /foo/ ? $a += 2 : $a -= 2 これは (/foo/ ? $a += 2 : $a) -= 2; のように間違って解析されてしまいます。 その一方で、 $a += /foo/ ? 1 : 2; これは C プログラマーが期待するであろう動作になりました。 =item * Precedence open FOO || die; これはもはや正しくなくなりました。ここではファイルハンドルを 括弧で括る必要があります。さもなければ、perl5 はこういった文を そのデフォルトの優先順位のまま放っておきます(以下の例参照)。 open(FOO || die); # perl4 opens or dies # perl5 opens FOO, dying only if 'FOO' is false, i.e. never =item * Precedence perl4 は特殊変数 C<$:> の優先順位に、perl5 が C<$::> を main パッケージと みなすのと同じ優先順位を与えます。 $a = "x"; print "$::a"; # perl 4 の出力: -:a # perl 5 の出力: x =item * Precedence perl には、ファイルテスト演算子と代入演算子を組み合わせたときに 優先順位のバグがありました。したがって、Perl4 の優先順位テーブルでは C<-e $foo .= "q"> は C<((-e $foo) .= "q")> と解釈すべきなのに実際には C<((-e $foo) .= "q")> と解釈していました。 Perl5 ではドキュメントにある通りの優先順位です。 -e $foo .= "q" # perl4 の出力: no output # perl5 の出力: Can't modify -e in concatenation =item * Precedence =begin original In perl4, keys(), each() and values() were special high-precedence operators that operated on a single hash, but in perl5, they are regular named unary operators. As documented, named unary operators have lower precedence than the arithmetic and concatenation operators C<+ - .>, but the perl4 variants of these operators actually bind tighter than C<+ - .>. Thus, for: =end original perl4 では、key()、each()、values() はシングルハッシュに対する 特別に高い評価順序を持った演算子でした。 しかし perl5 では、これらの演算子は通常の名前付き単項演算子となりました。 ドキュメントにある通り、名前付き単項演算子は、C<+ - .> のような 数学演算子や連結演算子よりも低い優先順位を持っています。 しかし、perl4 ではこれらの演算子よりも key() などのほうが強く演算対象と 結び付いていたのです。 したがって、以下の例のようになります: %foo = 1..10; print keys %foo - 1 # perl4 prints: 4 # perl5 prints: Type of arg 1 to keys must be hash (not subtraction) この perl4 の振る舞いは便利であるかもしれませんが、一貫性に欠けます。 =back =head2 General Regular Expression Traps using s///, etc. (s/// などを使ったときの一般的な正規表現の罠) =begin original All types of RE traps. =end original 正規表現に関する全てのタイプの罠。 =over 5 =item * 正規表現 C はもはやいずれの辺にあっても展開されなくなりました。 以前は $lhs は展開し、$rhs を展開しませんでした。 (文字列にあるリテラルの '$' にはいまでもマッチしません)。 $a=1;$b=2; $string = '1 2 $a $b'; $string =~ s'$a'$b'; print $string,"\n"; # perl4 の出力: $b 2 $a $b # perl5 の出力: 1 2 $a $b =item * 正規表現 C は、その状態を正規表現ではなく検索対象の文字列に 結び付けるようになりました (sub に対するブロックのスコープが残っているのであれば、 検索文字列の状態は失われます)。 $_ = "ababab"; while(m/ab/g){ &doit("blah"); } sub doit{local($_) = shift; print "Got $_ "} # perl4 prints: Got blah Got blah Got blah Got blah # perl5 の出力: infinite loop blah... =item * 正規表現 現在のところ、C 量指定子を無名サブルーチンの中にある正規表現で 使った場合、I<すべての> クロージャーはそのような無名サブルーチンから、 そういったクロージャの中で一番最初に使われたものの中で コンパイルされたかのような正規表現を生成します。 sub build_match { my($left,$right) = @_; return sub { $_[0] =~ /$left stuff $right/o; }; } $good = build_match('foo','bar'); $bad = build_match('baz','blarch'); print $good->('foo stuff bar') ? "ok\n" : "not ok\n"; print $bad->('baz stuff blarch') ? "ok\n" : "not ok\n"; print $bad->('foo stuff bar') ? "not ok\n" : "ok\n"; For most builds of Perl5, this will print: ok not ok not ok この例の場合、build_match() は常にC<最初>に build_match() が呼ばれたときの $left と $right の内容にマッチするようなサブルーチンを返します。 呼び出されたその時点での値ではありません。 =item * 正規表現 マッチングの中で括弧が使われなかった場合、perl4 では C<$+> には C<$&> と同じようにマッチした全体がセットされますが、 Perl5 ではそうではありません。 "abcdef" =~ /b.*e/; print "\$+ = $+\n"; # perl4 の出力: bcde # perl5 の出力: =item * 正規表現 置換は、失敗したときには空文字列を返すようになりました。 $string = "test"; $value = ($string =~ s/foo//); print $value, "\n"; # perl4 の出力: 0 # perl5 の出力: この新しい仕様に関しては L<数値に関する罠> も参照してください。 =item * 正規表現 C (バッククォートの使用)は通常の置換となり、 バッククォートの展開は行われなくなりました。 $string = ""; $string =~ s`^`hostname`; print $string, "\n"; # perl4 の出力: # perl5 の出力: hostname =item * 正規表現 正規表現中の変数の使用に関する構文解析がより厳密になりました。 s/^([^$grpc]*$grpc[$opt$plus$rep]?)//o; # perl4: compiles w/o error # perl5: with Scalar found where operator expected ..., near "$opt$plus" =begin original an added component of this example, apparently from the same script, is the actual value of the s'd string after the substitution. C<[$opt]> is a character class in perl4 and an array subscript in perl5 =end original 同じスクリプトでこの例に付け加えことは、 置換後の文字列の実際の値です。 C<[$opt]> は perl4 ではキャラクタクラスであり、perl5 では 配列の添え字となります。 $grpc = 'a'; $opt = 'r'; $_ = 'bar'; s/^([^$grpc]*$grpc[$opt]?)/foo/; print ; # perl4 の出力: foo # perl5 の出力: foobar =item * Regular Expression perl5 では、C は C と同様に一回だけマッチします。 perl4 では、C や C と同じように何度でもマッチします。 $test = "once"; sub match { $test =~ m?once?; } &match(); if( &match() ) { # m?x? が二回以上マッチ print "perl4\n"; } else { # m?x? が一回だけマッチ print "perl5\n"; } # perl4 の出力: perl4 # perl5 の出力: perl5 =back =head2 Subroutine, Signal, Sorting Traps (サブルーチン、シグナル、ソートの罠) =begin original The general group of Perl4-to-Perl5 traps having to do with Signals, Sorting, and their related subroutines, as well as general subroutine traps. Includes some OS-Specific traps. =end original Perl4 と Perl5 の違いの罠に分類される一般的なものは シグナル、ソート、そしてそれらに関連する サブルーチンで、いくつかの OS 固有の罠を含めた サブルーチンの罠と同じ様なものです。 =over 5 =item * (Signals) 文字列のように見える裸の単語は、その名前が使うよりも前に サブルーチンの名前として定義されている場合にはサブルーチンとして みなされます。 sub SeeYa { warn"Hasta la vista, baby!" } $SIG{'TERM'} = SeeYa; print "SIGTERM is now $SIG{'TERM'}\n"; # perl4 prints: SIGTERM is now main'SeeYa # perl5 prints: SIGTERM is now main::1 (and warns "Hasta la vista, baby!") B<-w> を使って、これを発見できます。 =item * (Sort Subroutine) reverse はもはやソートのサブルーチンの名前としては 使えなくなりました。 sub reverse{ print "yup "; $a <=> $b } print sort reverse (2,1,3); # perl4 prints: yup yup 123 # perl5 prints: 123 # perl5 warns (if using -w): Ambiguous call resolved as CORE::reverse() =item * warn() won't let you specify a filehandle. 常に STDERR に出力していたにもかかわらず、perl4 では warn() はファイルハンドルの 指定を必要としていましたが、perl5 では必要なくなりました。 warn STDERR "Foo!"; # perl4 の出力: Foo! # perl5 の出力: String found where operator expected =back =head2 OS Traps (OS の罠) =over 5 =item * (SysV) =begin original Under HPUX, and some other SysV OSes, one had to reset any signal handler, within the signal handler function, each time a signal was handled with perl4. With perl5, the reset is now done correctly. Any code relying on the handler _not_ being reset will have to be reworked. =end original HPUX 及び一部の SysV OS では、perl4 のときには シグナルが発生する度にそのシグナルハンドラ関数の中で シグナルハンドラを再設定しなければなりませんでした。 perl5 では、この再設定を正しく行うようになりました。 ハンドラを再設定しないということに依存したプログラムは 作業しなおす必要があります。 5.002 以降の perl では、SysV のときには sigaction() を使います。 sub gotit { print "Got @_... "; } $SIG{'INT'} = 'gotit'; $| = 1; $pid = fork; if ($pid) { kill('INT', $pid); sleep(1); kill('INT', $pid); } else { while (1) {sleep(10);} } # perl4 (HPUX) prints: Got INT... # perl5 (HPUX) prints: Got INT... Got INT... =item * (SysV) SysV OS では、 アペンドモード(C<<< >> >>>)でオープンしたファイルに対する C は fopen() マニュアルページにあるように正しく動作するように なりました。例えば、アペンドモードでファイルをオープンした場合には 既にファイルにある情報を上書きすることはできません。 open(TEST,">>seek.test"); $start = tell TEST ; foreach(1 .. 9){ print TEST "$_ "; } $end = tell TEST ; seek(TEST,$start,0); print TEST "18 characters here"; # perl4 (solaris) seek.test has: 18 characters here # perl5 (solaris) seek.test has: 1 2 3 4 5 6 7 8 9 18 characters here =back =head2 Interpolation Traps (展開の罠) =begin original Perl4-to-Perl5 traps having to do with how things get interpolated within certain expressions, statements, contexts, or whatever. =end original Perl4 と Perl5 の違いの罠には、式や文、コンテキストなどにおける 展開に関するものがあります。 =over 5 =item * Interpolation ダブルクォートで囲まれた文字列にある @ は常に配列に展開されます。 print "To: someone@somewhere.com\n"; # perl < 5.6.1, error : In string, @somewhere now must be written as \@somewhere # perl >= 5.6.1, warning : Possible unintended interpolation of @somewhere in string =item * Interpolation ダブルクォートで括られた文字列がエスケープされていない $ や @ で 終了することがなくなりました。 $foo = "foo$"; $bar = "bar@"; print "foo is $foo, bar is $bar\n"; # perl4 の出力: foo is foo$, bar is bar@ # perl5 errors: Final $ should be \$ or $name 注意:perl5 は、$bar の終端にある @ については“エラーにしません” =item * Interpolation Perl はダブルクォート中にあるブレースの内側の任意の式を 評価するようになりました(一般的には、C<$> や C<@> に続いて 開きのブレースがきたときです)。 @www = "buz"; $foo = "foo"; $bar = "bar"; sub foo { return "bar" }; print "|@{w.w.w}|${main'foo}|"; # perl4 の出力: |@{w.w.w}|foo| # perl5 の出力: |buz|bar| C を使って、perl5 におけるこのような罠を避けることが できることに注意してください。 =item * Interpolation =begin original The construct "this is $$x" used to interpolate the pid at that point, but now tries to dereference $x. C<$$> by itself still works fine, however. =end original "this is $$x" はプロセス ID を展開するようになっていましたが、 今は $x の参照外し(dereference)を試みます。 それでも C<$$> 自身は今でもきちんと動作します。 $s = "a reference"; $x = *s; print "this is $$x\n"; # perl4 の出力: this is XXXx (XXX はカレントプロセスID) # perl5 prints: this is a reference =item * Interpolation C を使ったその場(on the fly)でのハッシュの生成は ハッシュの名前を指定する C<$> がプロテクトされているか、もしくは 両方のカーリーブレースがプロテクトされていることを要求します。 両方のカーリーブレースがプロテクトされている場合には、perl4 と perl5 の結果は同じです。 $hashname = "foobar"; $key = "baz"; $value = 1234; eval "\$$hashname{'$key'} = q|$value|"; (defined($foobar{'baz'})) ? (print "Yup") : (print "Nope"); # perl4 の出力: Yup # perl5 の出力: Nope 以下のものを: eval "\$$hashname{'$key'} = q|$value|"; 次のように変更すると: eval "\$\$hashname{'$key'} = q|$value|"; 結果はこうなります: # perl4 の出力: Nope # perl5 の出力: Yup 以下のように変更した場合には eval "\$$hashname\{'$key'\} = q|$value|"; 結果はこうなります。 # perl4 の出力: Yup # perl5 の出力: Yup # これは両方のバージョンで同じ結果となります =item * Interpolation 以前のバージョンにあったバグに依存しているような perl4 プログラム。 perl -e '$bar=q/not/; print "This is $foo{$bar} perl5"' # perl4 の出力: This is not perl5 # perl5 の出力: This is perl5 =item * Interpolation 配列の参照についても注意する必要があります。 print "$foo{" perl 4 の出力: { perl 5 の出力: syntax error =item * Interpolation 同様に、以下のようなことも注意してください: $foo = "baz"; print "\$$foo{bar}\n"; # perl4 prints: $baz{bar} # perl5 の出力: $ perl5 は存在しない C<$foo{bar}> を探しに行きますが、perl4 は $foo を“baz”に展開しただけで満足します。 C でもこの事に注意してください。 =item * Interpolation C に C された文字列を渡した場合 eval qq( foreach \$y (keys %\$x\) { \$count++; } ); # perl4 runs this ok # perl5 prints: Can't find string terminator ")" =back =head2 DBM Traps =begin original General DBM traps. =end original DBMに関する一般的な罠。 =over 5 =item * DBM perl4 で(もしくは他の dbm/ndbm ツールで)作成した dbm データベースを、 perl5 の元で同じスクリプトで扱おうとすると失敗します。 perl5 の作成において、拡張 dbm の実装を C しないときに C がデフォルトで使用する関数のために (perl4 のときと同じ)同じ dbm/ndbm をリンクしていなければなりません。 dbmopen (%dbm, "file", undef); print "ok\n"; # perl4 の出力: ok # perl5 の出力: ok (IFF linked with -ldbm or -lndbm) =item * DBM key/value のサイズに関する制限を超えたときに発生するエラーにより、 perl5 では即座にプログラムから exit します。 dbmopen(DB, "testdb",0600) || die "couldn't open db! $!"; $DB{'trap'} = "x" x 1024; # ほとんどの dbm/ndbmには大きすぎる値 print "YUP\n"; # perl4 の出力 dbm store returned -1, errno 28, key "trap" at - line 3. YUP # perl5 の出力 dbm store returned -1, errno 28, key "trap" at - line 3. =back =head2 Unclassified Traps (未分類の罠) =begin original Everything else. =end original その他全て。 =over 5 =item * C/C の戻り値を使ったときの罠 doit.pl というファイルが sub foo { $rc = do "./do.pl"; return 8; } print &foo, "\n"; であって、do.pl が以下のような内容だったとすると、 return 3; doit.pl の実行結果はこうなります。 # perl 4 の出力: 3 (サブルーチンからすぐに抜けます) # perl 5 の出力: 8 C を C に置き換えても同じ振る舞いとなります。 =item * 空文字列に LIMIT を指定して C を使った場合 $string = ''; @list = split(/foo/, $string, 2) Perl4 は空文字列を持った一要素のリストを返しますが、Perl5 は 空リストを返します。 =back =begin original As always, if any of these are ever officially declared as bugs, they'll be fixed and removed. =end original いつものように、バグとして公式に宣言されたものがあれば、 それは修正されて取り除かれるでしょう。