時代遅れひとりFizzBuzz祭り、今回はPerl。前回がGNU AWKだったので、その流れでテキスト処理用の言語としての地位をAWKから掻っ攫っていったPerlにしてみた。実に安直だ。
Perlは殆ど触ったことがない。時々、拾ったツール*1がPerlで書かれてた等の理由でやむを得ずネットの情報を参考にして弄ることはあるけど、基本的に全く分かっていない。
なのでFizzBuzzも試行錯誤しながら書いてみた。ちなみに今更ながらPerl 5.8だ。
#!/usr/bin/perl use strict; use warnings; sub fizzbuzz { my ($n) = @_; my $val = ''; $val = 'Fizz' if ($n % 3 == 0); $val = $val . 'Buzz' if ($n % 5 == 0); $val = $n if ($val eq ''); return $val; } foreach my $i (1..100) { print &fizzbuzz($i), "\n"; }
Perlっぽい書き方なのか、そうでないのか不明。実はPerlでサブルーチンを初めて定義した。
偏見かもしれないけど、Perl使いならもっと短いコードを書くと思うので、もう少しだけ短くしてみた。
#!/usr/bin/perl use strict; use warnings; sub fizzbuzz { my ($n) = @_; my $val = ($n % 3 == 0) ? 'Fizz' : ''; $val = $val . 'Buzz' if ($n % 5 == 0); ($val eq '') ? $n : $val; } for (1..100) { print &fizzbuzz($_), "\n"; }
あまり短くなっていないけど、可読性とか含めて私にはこの辺が限界。
Perlはかなり自由に書けると思う。例えばLisp脳的データ変換な発想が混じったこんなコードとか。
#!/usr/bin/perl use strict; use warnings; sub fizzbuzz { my $val = ($_[0] % 3) ? '' : 'Fizz'; $val = $val . 'Buzz' unless ($_[0] % 5); ($val eq '') ? $_[0] : $val; } map {print "$_\n"} (map {fizzbuzz($_)} (1..100))
……あれ、間違えた。printの結果を更にリストにしてどうする。
改めて、こんなコード。
#!/usr/bin/perl use strict; use warnings; sub fizzbuzz { my $val = ($_[0] % 3) ? '' : 'Fizz'; $val = $val . 'Buzz' unless ($_[0] % 5); ($val eq '') ? $_[0] : $val; } foreach (map {fizzbuzz($_)} (1..100)) {print "$_\n"}
流石TMTOWTDI。
わざわざfizzbuzzを定義する必要も無いので、こうも書ける。
#!/usr/bin/perl use strict; use warnings; foreach (map { my $val = ($_ % 3) ? '' : 'Fizz'; $val = $val . 'Buzz' unless ($_ % 5); ($val eq '') ? $_ : $val; } (1..100)) {print "$_\n"}
……しかし問題が1つある。インデントや改行のスタイルがこれでよいのか分からない。一応、NTEmacsのデフォルトの設定でインデントしたらこうなった。
さて、ここで後学の為にPerl組み込みのデータ構造のうち、リストを触ってみることにした。まずは配列から。
#!/usr/bin/perl use strict; use warnings; sub fizzbuzz { my ($n) = @_; my @ref_tbl = ($n, 'Fizz', 'Buzz', 'FizzBuzz'); my $fizz = ($n % 3 == 0) ? 1 : 0; my $buzz = ($n % 5 == 0) ? 2 : 0; return $ref_tbl[$fizz + $buzz]; } for (1..100) { print &fizzbuzz($_), "\n"; }
そしてハッシュ。ハッシュにする意味はないけど、取り敢えず書いてみた。
#!/usr/bin/perl use strict; use warnings; sub fizzbuzz { my ($n) = @_; my %ref_tbl = ( 0 => $n, 1 => 'Fizz', 2 => 'Buzz', 3 => 'FizzBuzz' ); my $fizz = ($n % 3 == 0) ? 1 : 0; my $buzz = ($n % 5 == 0) ? 2 : 0; return $ref_tbl{$fizz + $buzz}; } for (1..100) { print &fizzbuzz($_), "\n"; }
分かりやすさ優先で「=>」を使っている。
非Perlユーザの私から見て、PerlはC言語系っぽく、sedっぽく、AWKっぽく、シェルスクリプトっぽく、Rubyっぽく*2、しかしどうしようもなくPerl的だ。今後使うかどうかは……$、@、%、&の記号の使い分けやコンテキストに悩まない程度にPerlに慣れない限り、短気な私には厳しいと思う*3。