argra****@users*****
argra****@users*****
2008年 4月 20日 (日) 20:34:23 JST
Index: docs/perl/5.10.0/perllol.pod diff -u /dev/null docs/perl/5.10.0/perllol.pod:1.1 --- /dev/null Sun Apr 20 20:34:23 2008 +++ docs/perl/5.10.0/perllol.pod Sun Apr 20 20:34:22 2008 @@ -0,0 +1,335 @@ + +=encoding euc-jp + +=head1 NAME + +=begin original + +perllol - Manipulating Arrays of Arrays in Perl + +=end original + +perllol - Perl で配列の配列を操作する + +=head1 DESCRIPTION + +=head2 Declaration and Access of Arrays of Arrays + +(配列の配列の定義とアクセス) + +組み立てるのが最も単純なことは、配列の配列(不正確にリストのリストとも +呼ばれることがあります)です。 +これは理解しやすく、そしてより複雑なデータ構造に対しても +適用することのできるものです。 + +配列の配列は、あなたが望めば通常の古い配列 @AoA のようなものです。 +これは C<$LoL[3][2]> のように、二つの添え字で要素を取得することができます。 +配列の宣言の例を挙げましょう。 + + # 配列に配列への参照の配列を代入する + @AoA = ( + [ "fred", "barney" ], + [ "george", "jane", "elroy" ], + [ "homer", "marge", "bart" ], + ); + + print $AoA[2][2]; + bart + +このとき、外側の括弧が丸括弧であったことに注意すべきです。 +これは、上の例では@配列に代入するので丸括弧を使う必要があったためなのです。 +もし@AoAではなくて、単にリファレンスを代入したかったというのであれば、 +次のように書くことができます。 + + # 配列への参照の配列に対する参照を代入 + $ref_to_AoA = [ + [ "fred", "barney", "pebbles", "bambam", "dino", ], + [ "homer", "bart", "marge", "maggie", ], + [ "george", "jane", "elroy", "judy", ], + ]; + + print $ref_to_AoA->[2][2]; + +外側の括弧が変わったことと、アクセスの構文が変わっているということに +注目してください。 +これはCとは違って、Perlでは配列と参照とを自由に交換できないからです。 +$ref_to_AoAは配列への参照です。 +その配列は@AoAで、これがまた配列です。 +同様に、C<$AoA[2]>は配列ではなく配列への参照です。 +ですから、 + + $AoA[2][2] + $ref_to_AoA->[2][2] + +これは、以下のような書き方でも同じことになります。 + + $AoA[2]->[2] + $ref_to_AoA->[2]->[2] + +この規則は隣り合った括弧(それが大かっこだろうが中かっこだろうが) +だけのものなので、参照外しをするarrowを自由に省略できます。 +けれども一番最初にあるarrowだけは、それがリファレンスを保持する +スカラであるために省略することはできません。 +これは$ref_to_AoAが常に必要とするものです。 + +=head2 Growing Your Own + +(大きくする) + +固定的なデータ構造の宣言は良いのですが、その場で新しい要素を +追加したいとき、あるいは完全に 0 から作り上げたいときにはどうするのでしょう? + +まず最初に、ファイルから読み込むことを見てみましょう。 +これは一度に一つの行を追加していくようなものです +私たちはここで、読み込んでいるファイルが、一行(line)が一つの行(row)に対応し、 +各単語が要素に対応しているようなフラットなファイルであると仮定しています。 +もし配列@AoAにそういった物を設定しようとするのであれば、 +それは以下のようなやり方になります。 + + while (<>) { + @tmp = split; + push @AoA, [ @tmp ]; + } + +関数を使って読み込むこともできます。 + + for $i ( 1 .. 10 ) { + $AoA[$i] = [ somefunc($i) ]; + } + +あるいは、配列に設定するために使う一時変数を使うこともできます。 + + for $i ( 1 .. 10 ) { + @tmp = somefunc($i); + $AoA[$i] = [ @tmp ]; + } + +配列への参照のコンストラクターであるC<[]>を使うことが非常に重要です。 +次のように書いてしまうのはとてもまずいやりかたです。 + + $AoA[$i] = @tmp; + +このようなスカラに対する名前付き配列の代入では、 + @ tmpにある要素の数を数えてその数を代入します。 +そしてこれはおそらくはあなたの望んだことではないでしょう。 + +C<use strict>の元で実行するのであれば、以下の様にちょっと宣言を +付け加えるとよいでしょう。 + + use strict; + my(@AoA, @tmp); + while (<>) { + @tmp = split; + push @AoA, [ @tmp ]; + } + +もちろん、一時的な配列もなければならないというものではありません。 + + while (<>) { + push @AoA, [ split ]; + } + +また、push()を使わなくてもできます。 +どこに押し込めたいかと言うことがわかっているのなら、 +直接代入させることもできます。 + + my (@AoA, $i, $line); + for $i ( 0 .. 10 ) { + $line = <>; + $AoA[$i] = [ split ' ', $line ]; + } + +あるいはこういう風にもできます。 + + my (@AoA, $i); + for $i ( 0 .. 10 ) { + $AoA[$i] = [ split ' ', <> ]; + } + +本当にそうしたいときを除き、スカラコンテキストでリストを返すかもしれない +関数を使ってしまう可能性に気をつけるべきです。 +これは普通の読み手には明らかでしょう。 + + my (@AoA, $i); + for $i ( 0 .. 10 ) { + $AoA[$i] = [ split ' ', scalar(<>) ]; + } + +配列へのリファレンスとして変数 $ref_to_AoAを使いたいというのであれば、 +以下の様にする必要があるでしょう。 + + while (<>) { + push @$ref_to_AoA, [ split ]; + } + +これで新しい行を追加することができます。 +新しいカラムを追加するのは? +あなたがまさに行列を扱っているのなら、大概は単純な代入となります。 + + for $x (1 .. 10) { + for $y (1 .. 10) { + $AoA[$x][$y] = func($x, $y); + } + } + + for $x ( 3, 7, 9 ) { + $AoA[$x][20] += func2($x); + } + +これは対象となる要素が既に存在しているかどうかには影響されません。 +(ない場合でも)喜んであなたのためにその要素を作り出し、必要に応じて +間にある要素にC<undef>をセットします。 + +あなたは、単に行に追加したいだけという場合であっても、 +ちょっと妙に見えることをしなければならないでしょう。 + + # 新たなカラムを既にある行に追加する + push @{ $AoA[0] }, "wilma", "betty"; + +次のようにはB<書けない>ことに注意してください。 + + push $AoA[0], "wilma", "betty"; # 間違い! + +事実、これはコンパイルすらできません。 +なぜでしょうか? +それはpush()の引数は参照ではなく、実際の配列でなければならないからです。 + +=head2 Access and Printing + +(アクセスと表示) + +こんどはこのデータ構造を出力する番です。 +あなたはどうやろうと考えてますか? +そうですね、簡単に要素を一つだけ出力したいとするとこうなります。 + + print $AoA[0][0]; + +配列の内容全部を出力したいとき、次のようには書けません。 + + print @AoA; # ダメ + +なぜなら、これでは単にリストへのリファレンスが 取れるだけで、 +perlはそれを自動的に参照外しするようなことはしないからです。 +このため、あなたは自分自身でループしなければなりません。 +これは外側の添え字に対するループでシェルスタイルのfor()を使って +構造全体を出力します。 + + for $aref ( @AoA ) { + print "\t [ @$aref ],\n"; + } + +添え字を記録したいのなら、このようにできます。 + + for $i ( 0 .. $#AoA ) { + print "\t elt $i is [ @{$AoA[$i]} ],\n"; + } + +あるいはこのようなやり方もあります。内側のループに注目してください。 + + for $i ( 0 .. $#AoA ) { + for $j ( 0 .. $#{$AoA[$i]} ) { + print "elt $i $j is $AoA[$i][$j]\n"; + } + } + +見て判るようにこれは少々複雑ですが、途中で一時変数を使えば簡単にできます。 + + for $i ( 0 .. $#AoA ) { + $aref = $AoA[$i]; + for $j ( 0 .. $#{$aref} ) { + print "elt $i $j is $AoA[$i][$j]\n"; + } + } + +うーんまだちょっと見にくいですね。 +これでどうでしょう: + + for $i ( 0 .. $#AoA ) { + $aref = $AoA[$i]; + $n = @$aref - 1; + for $j ( 0 .. $n ) { + print "elt $i $j is $AoA[$i][$j]\n"; + } + } + +=head2 Slices + +(スライス) + +多次元配列のスライス(行部分)を取りたいのであれば、fancy +subscripting(訳注: 風変わりな添え字付け?)をする必要があるでしょう。 +これは参照外しのためのpointer arrowを使った単一の要素に対するものは +あるのですが、それに対応するスライス用の便利なものはないのです。 +(もちろん、スライス操作をするためにループを書くことは常に +可能だと言うことを忘れないで下さい)。 + +以下は、ループを使った一つの操作をどのように行うかの例です。 +変数@AoAが前のものと同じであると仮定しています。 + + @part = (); + $x = 4; + for ($y = 7; $y < 13; $y++) { + push @part, $AoA[$x][$y]; + } + +このループをスライス演算に置き換えることができます。 + + @part = @{ $AoA[4] } [ 7..12 ]; + +あなたも見て感じるかもしれませんが、これは読み手にはちょっと不親切です。 + +あー、でも、$xを4..8、$yを7から12とするような B<二次元のスライス>を +必要とするときには? +うーん、単純なやり方はこうでしょう。 + + @newAoA = (); + for ($startx = $x = 4; $x <= 8; $x++) { + for ($starty = $y = 7; $y <= 12; $y++) { + $newAoA[$x - $startx][$y - $starty] = $AoA[$x][$y]; + } + } + +スライスを使ってループを簡単にできます。 + + for ($x = 4; $x <= 8; $x++) { + push @newAoA, [ @{ $AoA[$x] } [ 7..12 ] ]; + } + +あなたがシュワルツ変換に興味を持っているのなら、 +mapを使って次のようにすることを選ぶかもしれません。 + + @newAoA = map { [ @{ $AoA[$_] } [ 7..12 ] ] } 4 .. 8; + +あなたの上司が不可解なコードによるジョブセキュリティ(もしくは +rapid insecurity)の追求を非難していたとしても、 +説得するのは難しいでしょうね :-) +もし私があなたの立場だったら、こういった操作は関数に押し込めるでしょう。 + + @newAoA = splice_2D( \@AoA, 4 => 8, 7 => 12 ); + sub splice_2D { + my $lrr = shift; # リファレンスのリストのリストへのリファレンス! + my ($x_lo, $x_hi, + $y_lo, $y_hi) = @_; + + return map { + [ @{ $lrr->[$_] } [ $y_lo .. $y_hi ] ] + } $x_lo .. $x_hi; + } + +=head1 SEE ALSO + +perldata(1), perlref(1), perldsc(1) + +=head1 AUTHOR + +Tom Christiansen <F<tchri****@perl*****>> + +Last update: Thu Jun 4 16:16:23 MDT 1998 + +=begin meta + +Translate: KIMURA Koichi (5.005_03) +Update: Kentaro Shirakata <argra****@ub32*****> (5.6.1-) + +=end meta + Index: docs/perl/5.10.0/perlop.pod diff -u docs/perl/5.10.0/perlop.pod:1.3 docs/perl/5.10.0/perlop.pod:1.4 --- docs/perl/5.10.0/perlop.pod:1.3 Mon Mar 10 18:34:30 2008 +++ docs/perl/5.10.0/perlop.pod Sun Apr 20 20:34:22 2008 @@ -697,17 +697,15 @@ C<$a> と C<$b> の整数部のみが操作で使われます (注意: ここで C<UV_MAX> は符号なし整数の最大値を意味します)。 右オペランドの絶対値 (C<abs($b)>) が C<(UV_MAX + 1)> 以上の場合、 -"%" computes the floating-point remainder -C<$r> in the equation C<($r = $a - $i*$b)> where C<$i> is a certain -integer that makes C<$r> should have the same sign as the right operand -C<$b> (B<not> as the left operand C<$a> like C function C<fmod()>) -and the absolute value less than that of C<$b>. +"%" は、C<($r = $a - $i*$b)> となる浮動小数点剰余 C<$r> を計算します; +ここで C<$i> は、C<$r> が右オペランド C<$b> と同じ符号 (C の +関数 C<fmod()> のように左オペランド C<$a> B<ではありません>) で、 +絶対値が C<$b> より小さいものになるような、ある整数です。 C<use integer> がスコープ内にある場合、 "%" は C コンパイラで実装された剰余演算子を使います。 この演算子は被演算子が負の場合の挙動が不確実ですが、 より高速です。 X<%> X<remainder> X<modulus> X<mod> -(TBT) =begin original @@ -2299,14 +2297,13 @@ =end original -The character following C<\c> is mapped to some other character by -converting letters to upper case and then (on ASCII systems) by inverting -the 7th bit (0x40). The most interesting range is from '@' to '_' -(0x40 through 0x5F), resulting in a control character from 0x00 -through 0x1F. A '?' maps to the DEL character. On EBCDIC systems only -'@', the letters, '[', '\', ']', '^', '_' and '?' will work, resulting -in 0x00 through 0x1F and 0x7F. -(TBT) +C<\c> に引き続く文字は、英字は大文字に変換された後、(ASCII システムでは) +7 番目のビット (0x40) を反転させることで別の文字にマッピングされます。 +最も興味深い範囲は '@' から '_' (0x40 から 0x5F) で、結果として +コントロール文字 0x00 から 0x1F になります。 +'?' は DEL 文字にマッピングされます。 +EBCDIC システムでは '@', 英字, '[', '\', ']', '^', '_', '?' のみが +動作し、結果として 0x00 から 0x1F と 0x7F になります。 =begin original @@ -3854,9 +3851,8 @@ =end original -Double quotes indicate that the text will be interpolated using exactly -the same rules as normal double quoted strings. -(TBT) +ダブルクォートは、通常のダブルクォートされた文字列と全く同じ規則を使って +変数展開されることを示します。 print <<EOF; The price is $Price. @@ -3909,11 +3905,10 @@ =end original -The content of the here doc is treated just as it would be if the -string were embedded in backticks. Thus the content is interpolated -as though it were double quoted and then executed via the shell, with -the results of the execution returned. -(TBT) +ヒヤドキュメントのの内容は、文字列がバッククォートで +埋め込まれているかのように扱われます。 +したがって、その内容、はダブルクォートされているかのように変数展開され、 +その後シェル経由で実行され、実行された結果になります。 print << `EOC`; # execute command and get results echo hi there @@ -4149,8 +4144,9 @@ The first pass is finding the end of the quoted construct, where the information about the delimiters is used in parsing. -During this search, text between the starting and ending delimiters -is copied to a safe location. The text copied gets delimiter-independent. +検索中に、開始デリミタと終了デリミタの間のテキストは安全な場所に +コピーされます。 +コピーされたテキストはデリミタに依存しません。 (TBT) =begin original @@ -4165,14 +4161,13 @@ =end original -If the construct is a here-doc, the ending delimiter is a line -that has a terminating string as the content. Therefore C<<<EOF> is -terminated by C<EOF> immediately followed by C<"\n"> and starting -from the first column of the terminating line. -When searching for the terminating line of a here-doc, nothing -is skipped. In other words, lines after the here-doc syntax -are compared with the terminating string line by line. -(TBT) +構造がヒヤドキュメントの場合、終了デリミタは内容として終端文字列を持つ +行です。 +従って、C<<<EOF> は、C<"\n"> の直後の、終端行の最初の列から始まる C<EOF> で +終端します。 +ヒヤドキュメントの終端行を探すとき、読み飛ばされるものはありません。 +言い換えると、ヒヤドキュメント文法以降の行は、1 行毎に終端文字列と +比較されます。 =begin original @@ -4246,13 +4241,12 @@ 最初のデリミタが開きかっこでない場合、C<s!!!> and C<tr)))> のように 3 つのデリミタは同じでなければなりません; この場合、2 番目のデリミタが左側の終端と右側の開始を同時に行います。 -If the left part is delimited by bracketing punctuations (that is C<()>, -C<[]>, C<{}>, or C<< <> >>), the right part needs another pair of -delimiters such as C<s(){}> and C<tr[]//>. In these cases, whitespaces -and comments are allowed between both parts, though the comment must follow -at least one whitespace; otherwise a character expected as the start of -the comment may be regarded as the starting delimiter of the right part. -(TBT) +左側のデリミタがかっこを構成するもの (これは C<()>, +C<[]>, C<{}>, C<< <> >> のいずれか) の場合、右側も +C<s(){}> や C<tr[]//> のようなデリミタである必要があります。 +これらの場合、右側と左側の間には空白やコメントを置けますが、 +コメントは少なくとも一つの空白の後である必要があります; +さもなければコメントの開始文字が右側の開始デリミタとして扱われてしまいます。 =begin original @@ -4386,10 +4380,10 @@ 変数展開は行われません。 String modifying combinations for case and quoting such as C<\Q>, C<\U>, and C<\E> are not recognized. -The other escape sequences such as C<\200> and C<\t> and backslashed -characters such as C<\\> and C<\-> are converted to appropriate literals. -The character C<-> is treated specially and therefore C<\-> is treated -as a literal C<->. +C<\200> や C<\t> のようなその他のエスケープシーケンスや、 +C<\\> や C<\-> のようなバックスラッシュ付きの文字は、適切なリテラルに +変換されます。 +文字 C<-> は特別扱いされるので、C<\-> はリテラルな C<-> として扱われます。 (TBT) =item C<"">, C<``>, C<qq//>, C<qx//>, C<< <file*glob> >>, C<<<"EOF"> @@ -4575,9 +4569,9 @@ However any other combinations of C<\> followed by a character are not substituted but only skipped, in order to parse them as regular expressions at the following step. -As C<\c> is skipped at this step, C<@> of C<\c@> in RE is possibly -treated as an array symbol (for example C<@foo>), -even though the same text in C<qq//> gives interpolation of C<\c@>. +ここでは C<\c> は読み飛ばされるので、正規表現中の C<\c@> の C<@> は +配列のシンボル(例えば C<@foo>) と扱われる可能性があります; +一方 C<qq//> 内の同じテキストは C<\c@> と展開されます。 (TBT) =begin original