Perlがくしゅう帳(Rubyも)

プログラミングの勉強会の参加記録や学んだことなど。 twitter ID : @tomcha_で活動しています。 最近は主にPerl関連の勉強会やコミュニティに参加しています。移転前のブログはこちら->http://ruby.doorblog.jp/

Perlのmapについて

Perl入学式in大阪第5回「map関数」についての補足事項です。

講義中に自分でテストコードを書いて試してからツイートをしたのですが、mapの話が懇親会で話題にあがり、@azumakuniyukiさんより、「mapは破壊的関数ちゃうのん?」と指摘があり、 その後にもう少し突っ込んでサンプルコードを試したところ、ツイートの「mapは、元のデータを書き換えるのではなく」は誤っていました。すみませんでした。

結論

map関数は「破壊的関数」であり、元の配列のデータは更新(上書き)されるケースがあります。

更新されるケースとは?

こういう事はコードを書いて実験するのが一番です。
4つのパターンのmap関数使用例を書いてみました。

mapのテスト

講義中にササッと書いてテストしたのはコード14行目の"a"のパターンです。
この使い方だと、確かに元の配列@aの中身は変更されず、別の配列@bに代入された結果だけが'.bak'を付加されているので、一見、「map関数は元の配列データを更新しない」様に見えます。

しかし、本当にそうだったのでしょうか? コード17行目"c"のパターン、コード18行目"d"のパターンともに元の配列@aaのデータは正規表現の条件式に当てはまるデータは".bak"を付加され、データが更新されていました。

"c"、"d"は正規表現の置換のコードです。$の値が置換されますね。それに対して"a"のパターンは$の値を”参照”はしているものの、代入する表現は含まれていません。代入をするパターンとして、コード15行目を試してみると、何と@aは元の配列のデータが更新されました。

この実験コードのテストから、$_は元の配列の個々のデータを参照しているので、当然書き換えれば元の配列のデータは書き換わることが分かります。ということは、「mapは破壊的関数で元のデータを更新する」という事ですね。

ただし、パターン"a"の様な、配列のデータを参照にとどめている場合は自動で更新されません。
なので、「mapは破壊的関数で元のデータを更新するが、中の式によって更新しないケースもあるので、ケースに応じて意図した通りに元の配列が更新されるか(又は更新されないか)を注意する必要がある」という事ですね。

結論その2

という事で、この話題も懇親会で色々講義の内容をワイワイ話した結果得られた知見でした。
懇親会、大事ですね。ざっくばらんに質問したり、話をしたりできる場ですので、講義だけでは聞けなかった事や、間違って解釈してしまっていた事が分かる場でもあります。また、サポーター陣も完全では無いので、今回のように間違いを発見できる場でもありました。

f:id:tomcha0079:20150117181044j:plain

f:id:tomcha0079:20150117195013j:plain

懇親会、大事。