本連載では第一線のPerlハッカーが回替わりで執筆していきます。今回のハッカーはkarupaneruraこと佐藤健太さんで,
本稿のサンプルコードは,
短くシンプルにコードを書き上げるテクニック
みなさんもご存じのとおり,
このとき,
そんな場面においては,
そこで今回は,
まず
特殊変数$_
を使う
Perlの特色の一つとして,$_
の存在が挙げられるでしょう。この特殊変数の役割は大きく分けて2つあります。一つは,foreach
のループ値の変数の指定を省略した際に$_
へ自動的にループ値が代入されるような,uc
などの組込み関数のデフォルトの引数としての役割です。
$_
は暗黙的に使われるものであるため,$_
をやみくもに使うと,$_
を使うと,$_
なのか見分けが付きにくく,
しかし,map
やgrep
など処理する対象が自明である場合にも便利です。$_
の使いどころを考えるヒントを表1にまとめました。
表1 $_の使いどころを考えるヒント
検討事項 | 使ってもよい場面 | 使うべきでない場面 |
---|---|---|
必要な事前処理 | 少ない | 多い |
扱うデータの種類 | 少ない | 多い |
処理の内容 | 単純 | 複雑 |
処理の対象 | 自明 | 自明ではない |
ワンライナーで使う
$_
を便利に活用できる代表的なユースケースとして,
次のコードは,
$ perl -e 'print "Hello, World!\n"'
ちょっとした問題を手早く片付ける際に,grep
やsed
などのUNIXコマンドだけでは複雑になる場面でも,
そして,$_
は非常に便利に使えます。たとえば,
$ perl -pe '$_=uc'
処理系perl
の-p
オプションを使用することで,
B::Deparseを用いて展開したコード
LINE: while (defined($_ = readline ARGV)) {
$_ = uc $_;
}
continue {
die "-p destination: $!\n" unless print $_;
}
引数に指定したコードがループの中に展開されます。これは,continue
セクションでprint
するしくみです。そして,uc
の引数が,$_
に補完されています。
別の例として,sed
の代替としてperl
を使って,
$ perl -pe 's/foo/bar/g'
この例も,=~
を利用せずに正規表現による置換を行うため,$_
が処理の対象になります。結果として,sed
のような処理をこれだけで実現できます。
このように,
ちなみに,perl
にはほかにも-n
や-a
などさまざまなコマンドラインオプションが実装されています。それぞれのオプションが問題にはまれば,
foreach
と組み合わせて使う
一般的にforeach
はループを書くときに使われますが,$_
を代入するためだけに使うこともできます。なお,foreach
はfor
と等価ですので,for
として説明します。
次の例では,$fizzbuzz_
がfizzかbuzzを含む場合に文字列を出力します。
say "$fizzbuzz_text includes fizz"
if $fizzbuzz_text =~ /fizz/;
say "$fizzbuzz_text includes buzz"
if $fizzbuzz_text =~ /buzz/;
十分わかりやすいですが,$fizzbuzz_
という名前は長く見通しが悪いです。かといって,
for
を使って書きなおすと,
for ($fizzbuzz_text) {
say "$_ includes fizz" if /fizz/;
say "$_ includes buzz" if /buzz/;
}
for
は通常リストに対してループを行いますが,$_
が使われます。結果的にこのfor
のブロックは,$_
を$fizzbuzz_
として扱うブロックとして使えます。そして,=~
演算子を利用せずに正規表現マッチを行っているため,$_
がその処理の対象になります。
しくみは少し複雑ですが,