Perl入学式#6の補講に参加
今月もPerl入学式 プログラミング初心者のためのPerl入門講座の第6回目に参加した。と思いきや当日体調不良のため欠席。その代わりに補講に出てきた。
参加者3名に対して講師2名という贅沢な構成。意外と補講の方がお勧めかもしれん。
だんだん新しい概念の話題はなくなってきて、これまでの復習になってきた。本講であまり先に進めなかった事情もあったのかもね。
1.関数の復習
名前と身長と体重をコンソールから入力して、BMI値と共に結果をコンソールに表示する。
my %person; print "名前: "; chomp($person{name} = <STDIN>); print "身長(cm): "; chomp($person{height} = <STDIN>); print "体重(kg): "; chomp($person{weight} = <STDIN>); sub calc_bmi { my ($weight, $height) = @_; return $weight / ( ($height / 100.0) **2 ); } my $bmi = &calc_bmi($person{weight}, $person{height}); printf("%sさんのBMI値は%.2fでした\n", $person{name}, $bmi);
今回はこれをハッシュのリファレンスを渡すことで、せっかく作った %person を生かしたい、という課題。書き換えるとこんな風
sub calc_bmi { my ($person) = @_; return $person->{weight} / ( ($person->{height} / 100.0) **2 ); } my $bmi = &calc_bmi(\%person);
誰しも思うところは、こう書き換えてしまうと calc_bmi が引数としてどんなものを要求しているのかわかり難くなる。これは Perl に限らず Ruby でも似たような事情にあると思う。
講義ではバリデータのようなモジュールを利用することもある、程度でさらっと流れる。ググってみると色々ある。試しに Smart::Args とかで書くと
use Smart::Args; sub calc_bmi { args my $name => { optional => 1}, my $height => 'Int', my $weight => 'Int'; return $weight / ( ($height / 100.0) **2 ); } my $bmi = &calc_bmi(%person);
多分、こんな感じ。
今回やったのは、おおまかに言うとこれ位。あとは後置 if とか unless とか、ループで脱出する時に last とか。
2.質問タイム
前回疑問のまま放置していた、utf-8 でエンコードされた日本語ファイルの入出力の件について質問しておいた。非常に適当に要約すると、ファイルを読込む時や書き込む時に必要とするエンコーディングを
open my $fh, "<:encoding(UTF-8)", "file1.txt" or die;
とか
open my $fh, ">:utf8", "file2.txt" or die;
のように指定してやると、Perlの内部エンコードとファイルの持っている外部エンコーディングを相互に変換してくれるようだ。
Encode::encode_utf8($line);
のように一々変換してもいいようだが、面倒なだけだな。ただ qx{} で戻ってくるコマンドの結果はやはり外部エンコーディングの UTF-8 なのでそれを Perlスクリプト内で利用しようとすると
my $result = Encode::decode_utf8(`some_command`);
のように内部エンコーディングにデコードする必要があるようですな。