2013-12-12autovivificationとうまく付き合うこんにちは。PlackとAnyEventが好きですがautovivificationも好きです。今回はautovivificationプラグマについて書いてみます。0.12autovivificationって?undefの入った変数が配列やハッシュとしてdereferenceされる際に配列やハッシュオブジェクトが自動的に生成される機能です。公式ドキュメントにはperlrefに記載があります。};とまあ、初期化もしてない変数$dataをいきなりdereferenceしてデータをブッこんでもよしなに構造を作ってくれます。};と、undefなフィールドに対していきなりpushできたりします。便利ですね!autovivificationが牙を剥く瞬間こんな便利なautovivificationですが、時としてビックリさせられることがあります。上の例のように書き込み操作ではそうでもないのですが、読み込み操作でautovivificationが発生することもあるので注意が必要なのです。};おや、%dataには一切代入をしていないのにいろいろautovivifyされましたね。これは、defined($data{foo}{bar}{buzz}{hoge})を評価する際に$data{foo}や$data{foo}{bar}などが順番にハッシュとしてdereferenceされることでそれらがautovivifyされているからだと考えられます。definedではなく、existsを使っても同様です。いって大抵の場合どうってことないんですが、この後でData::Transformerとか使うと予想外の事態になりそうですね。いったautovivificationをクソマジメに防ぐにはこうします。{};はい、だいぶダルくなってきました。autovivification"autovivificationはautovivificationの有効・無効を切り替えてくれるプラグマモジュールです。autovivification;のようにnoキーワードとともに使い、autovivificationを部分的に無効化します。これを使うと、先程の例はこう書けます。autovivificationと先頭に書くだけでOKです。autovivificationが有効になっている状態でも、代入を行うとautovivificationが発生します。};まあ代入するなら普通はautovivifyしてほしいですよね。サイコーですね!!なお、設定次第で代入時のautovivificationも禁止することができます。詳しくはドキュメントを参照して下さい。autovivification"って書いたのにautovivifyするけど?下の例を見て下さい。[];「$data->[0]が存在したらそれをprintする」という処理を2通りの書き方で書いているだけですが、関数print_if_anyを経由するとautovivificationが起こってしまっています。これは、関数への実引数渡しが代入と同等に扱われているためだと考えられます。Perlでは実引数は参照渡しであり、呼び出された関数はその内容を書き換えることができます。];このようなこともあるため、関数への実引数渡しではautovivificationが発生してしまいます。同様のことはfor文でも起こるようです。autovivificationプラグマのドキュメントをよく読めば書いてあることなんですが、わりと盲点になりがちなトコロだと思っています。まとめPerlの便利な機能"autovivification"と、それを部分的に無効化するプラグマモジュールautovivificationについてご紹介しました。autovivification"と書くだけでいい感じの挙動になるのは嬉しいですね。