Perl ではスカラーコンテキストとリストコンテキストが肝の一つなんだけれど、ここ最近 C++ を使うことが多かったこともありリファクタリングでちょっとポカった。
#!/usr/bin/perl use warnings; use strict; use Data::Dumper; sub f { return; } sub g { return undef; } my $f_value = f; my $g_value = g; my $f_hash = { a => 1, b => $f_value, c => 3}; my $g_hash = { a => 1, b => $g_value, c => 3}; print Dumper($f_hash, $g_hash); #$VAR1 = { # 'c' => 3, # 'a' => 1, # 'b' => undef # }; #$VAR2 = { # 'c' => 3, # 'a' => 1, # 'b' => undef # };
リファクタリング前のコード。$f_hash も $g_hash も同じ。 ここでリファクタリングのスタンダード「一時変数のインライン化」を行う。
my $f_hash = { a => 1, b => f, c => 3}; my $g_hash = { a => 1, b => g, c => 3}; print Dumper($f_hash, $g_hash); #Odd number of elements in anonymous hash at test.pl line 13. #$VAR1 = { # 'a' => 1, # '3' => undef, # 'b' => 'c' # }; #$VAR2 = { # 'c' => 3, # 'a' => 1, # 'b' => undef # };
ああ。f の呼び出しがリストコンテキストに変わるので、 return; が undef ではなく () を返すようになり無名ハッシュを生成するリストの中で消えてしまうため、キーと値の組み合わせがずれてしまう(そして無名ハッシュを奇数個の要素で作ろうとする警告も出る)。
コンテキストは理解しているんだけれど、リファクタリング前のコードでスカラー変数で受けているので、つい f がスカラー値だけを返すサブルーチンだと錯覚してしまうと。
g みたいに明示的に return undef; してればいいかというと、これはこれで落とし穴があり、一般的には return; の方が推奨されている。
テストスクリプトで 「クラスメソッドの返り値のアサーションで、is に括弧をつけると動くけれど、とると動かなくなるのはなぜ?」とチームメンバに質問された。
#!/usr/bin/perl use warnings; use strict; use 5.10.0; package MyClass; sub color { 'blue' }; package main; use Test::More; is(MyClass->color, 'blue'); is MyClass->color, 'blue'; # wrong! done_testing;
簡略化すると上のような感じ。実行すると、
Useless use of a constant (blue) in void context at sample.t line 16. ok 1 Can't locate object method "is" via package "MyClass" at sample.t line 16. # Tests were run but no plan was declared and done_testing() was not seen.
となる。
これは間接オブジェクト構文(indirect object syntax)の罠にハマったケースだね。 間接オブジェクト構文は、例えば C++ の new っぽく
my $obj = new MyClass;
と書ける構文(MyClass::new が呼ばれる)。前述では MyClass::is 呼ぼうとして怒られていると。間接オブジェクト構文は perldoc perlobj で説明されている。
ちなみにis じゃなくて組み込み関数だと違う解釈になる。
say(uc MyClass->color);
とすると MyClass::uc が呼ばれるのではなくて uc(MyClass->color) と解釈されるので "BLUE\n" が出力される。
また以下みたいに、意図しないまま動いちゃう場合もあるので注意かな。
#!/usr/bin/perl use warnings; use strict; use 5.10.0; package MyClass; sub color { 'blue' }; sub is { 'MyClass2' } package MyClass2; sub color { 'red' }; package main; use Test::More; is MyClass->color, 'green'; done_testing;
これだと MyClass::is が呼ばれて 'MyClass2' が返ってきて、そして MyClass2 の color が呼ばれて 'red' が返ってくる(そして 'green' は使われないし、Test::More::is も実行されない)。
Useless use of a constant (green) in void context at sample.t line 21. 1..0 # No tests run!
困ったらカッコつけようぜ。
インスタンスオブジェクト毎に固有の変数といえばインスタンス変数である。コンテキストによって呼び名が微妙に違ったりして、C++ だとメンバ変数と呼ばれている。オブジェクト指向一般論ではなく、特定のプログラミング言語における話ではできるだけその世界の用語を使うようにしている。
けどそういえば Perl だと何て呼ぶのだろう。これだという話もあまり聞かない。あと Perl だとインスタンスは bless された何かであってインスタンス毎の値をどう格納するかはまちまちのなので「変数」と呼ぶのも何か気持ち悪い。なのでつい「スロット」と呼んでいたのだけれどどっちかというと Lisp 方面的な呼び方だし、多分チーム内でも伝わっていなかったと思う。
ということで Perl のドキュメントを漁ったら perlootut で attribute って呼んでいた。
なのでとりえず Perl コンテキストでは attribute と呼ぶことにしよう。
[ Perl 用語 ]
今日も朝から YAPC::Asia Tokyo 2015 の2日目です。まずは一杯の無限オレンジジュースからスタート。最初はトラックCから。 C の部屋に入れたのはこれが初めてです。なるほど狭め。
言語の特性にあわせて様々なプログラミング言語を活用しているというトーク。サーバサイドで使われているということでちょっと Scala が気になりますが、やはりここでもコンパイルが遅いという話が出ていました。
Go は小さなシングルバイナリを作れるというところがやはり大きな利点。あとはやっぱり Perl はビルドなどのためのツールを作るのに便利だよねという話でした。
Ricardo Signes 氏のトークを聞くのは YAPC::Asia Tokyo 2013 1日目の時(記事)以来です。
前回同様 Perl の機能追加・削除についての話が中心。直観に反するような挙動が修正されるというところは言語としての完成度があがって良いなと。一方、さらに experimental として追加される文法は、ますます変態的になっていくなという印象もありました。
今日は一人でぶらりとTFTビルへ。
リファクタリングを行う理由の中で「Developer Education」という話があって、理解のためにリファクタリングをしてもらうのも良いと言っていて、ああそうだよなと思いました。リファクタリングの素養はあるけれども、チームのコードは知らないという状態の時にはいいなと思います。
あとは、基本的には Martin Fowler の「リファクタリング」を読んでいれば OK な感じです。
ちょっとうつらうつらしてました。あと「カレのヒゲ」はマイクにこすれるので通訳的に要注意のようでした。
Perl 6 における 並列・並行・非同期処理の話。 Perl 6 では言語レベルでこのあたりのサポートがしっかり入ってくるという印象でした。昨日聞いたトークといい、やはり Perl 6 が気になってきました。
Go の各種ツールを使って時間やメモリを消費している部分を見つけてどんどん削っていく様子をライブで実演してくれました。なるほど、ちょっとしたコードでも工夫すると劇的に最適化できるみたいです。
実演中アセンブラコードをチェックしているところや、データが 1 word から 3 words で管理されているという説明などをみて、ああやっぱり Go は C/C++ 的なマシンへの近さやコンパクトさがあるよなとあらためて感じました。
YAPC::Asia Tokyo 最後のトーク(になるかもしれない)となった LT は Kuniwak (@orga_chem) 氏の「Vim script性的解析の光と闇」でした。
CONBU さんが LT の時間内で設営・撤収デモまで実演していて、その素早さに驚嘆でした。まさに神業のレベルです。会期中お世話になりました。
今年はキーノートが無いので LT が終わるとクロージングです。
今年の参加者はなんと約2,130人。今の形での開催は最後と言われている YAPC::Asia は今後どうなっていくのでしょうか。 YAPC::Asia Tokyo 2015 は「The End.」のスライドで幕を閉じました。皆さんお疲れさまでした。
去年の YAPC::Asia Tokyo 2014 では Go 言語の勢いを感じ、その後ちょっとした規模ですが業務ツール開発に使ってみたりしました。
YAPC::Asia Tokyo 2015 では近年になく Perl のトークを見た気がします。しかも今回は Perl 6 のコードををよく見た気がするのは気のせいでしょうか。今回はこれを機に Perl 6 にチャレンジしていきたいと思います。
Naney (なにい) です。株式会社MIXIで SNS 事業の部長をしています。
※本サイトの内容は個人的見解であり所属組織とは関係ありません。