Perl入学式 #7補講に参加した

課題に対する私の回答などは前回のエントリーにあるので興味のある人はどうぞ。このエントリーは主に感想などを。

全体の感想

毎度のことだけど、詰め込みすぎ。今回は、map / grep の話と正規表現の話になってましたが、3時間の枠でこれだけの話をするのは無理がある。
いずれの話題も初学者には非常にとっつき難いので、もっと沢山演習を用意して色んなパターンを参加者が試すことができるようにした方がよいと感じた。

個別の話題

grep / map

多用するとコードが厨二っぽくなるアレ。講義の中では自前で grep のようなブロックを取る関数を定義するのは無理、というような話だったけど、List::Util::reduce とかあるので、プロトタイプ宣言すれば定義できるような気がする。
でもローカル変数の使い方がやっぱりよくわからん、自ら進んで定義しようとは思わんな、無名関数を引数に渡してしまった方が簡単だしわかりやすい。唯一、

map { .. } grep { .. } @list

みたいにチェーンしたい場合には有効なのかもしれん。でも ruby の書き方の方が好き。

list.select { |x| ... }.map { |x| ... }

慣れの問題か?

正規表現

話しだすときりがない、講義中にツイートしたように最初は「.* で任意の文字列にマッチする」程度でけっこう戦える。
講義中では正規表現のサンプルのために

下記の場合に出力しない
文字列がjohn, Johnを含む.
文字列の先頭にbetty, Bettyを含む.
文字列の最後にgreat, Greatを含む.
文字列がtomというアルファベットを含む(大文字・小文字問わず).

て感じの条件を一つの正規表現で頑張っていましたが、普通は個別に対応すればいいと思う

sub contain_john {
  return $_[0] =~ /john|John/; 
}
sub start_with_betty {
  return $_[0] =~ /^(betty|Betty)/;
}
sub end_with_great {
  return $_[0] =~ /(great|Great)$/;
}
sub contain_tom {
  return $_[0] =~ /tom/i;
}
sub allow_print {
  my $target = shift;
  return 0 if contain_john($target);
  return 0 if start_with_betty($target);
  return 0 if end_with_great($target);
  return 0 if contain_tom($target);
  return 1;
}
while (my $line = <STDIN>) {
  print $line if allow_print($line);
}

みたいに。あるいは switch を使うとか

use feature qw/switch/;

sub allow_print {
    given($_[0]) {
        when (/john|John/)      { 0 }
        when (/^(betty|Betty)/) { 0 }
        when (/(great|Great)$/) { 0 }
        when (/tom/i)           { 0 }
        default { 1 }
    }
}
while (my $line = <STDIN>) {
  print $line if allow_print($line);
}

演算子 =~ の動作が(スカラコンテキストとリストコンテキストで?)非常にわかり難かったので、ほんとうはもっと突っこんで聞いておきたかった。時間切れ。

その他

発表資料で利用されているプレゼンツールがちょっと不便。先頭ページからカーソルキーで順番にしかアクセスできない線形リスト方式なので、後で「配列の参照についてどっかで説明されていたはず」と思って探そうとしても、順番にページをめくっていくしかない。そしてページめくりのエフェクトがすげー邪魔。