Perl Hackers Hub

第57回 自作ツールによる日常業務効率化―初歩的なコードだけで身近な問題を解決!(2)

この記事を読むのに必要な時間:およそ 5.5 分

ゲーム感覚で英単語を学習する

これまでに紹介したツールは,おもに業務の効率化や負担軽減を目的としていましたが,ここで少し趣が異なるプログラムを紹介します。

Perlの入門初期にwhile文や標準入出力の方法を教わると,必ずと言ってよいほど練習問題として出題されるのがじゃんけんゲームです。

janken.pl

say '数字を入力してください。
1: グー, 2: チョキ, 3: パー';

my %janken = (
    1 => 'グー', 2 => 'チョキ', 3 => 'パー',
);

while (1) {
    print '> ';
    my $input = <STDIN>;
    chomp $input;
    next if $input !~ /[123]/;

    my $output = int(rand(3));
    $output++;

    say "あなた: $janken{$input}";
    say "わたし: $janken{$output}";

    my $result = $input - $output;

    if ($input == $output) {
        say "あいこ";
    }
    elsif ($result == 2 || $result == -1) {
        say "あなたの勝ち";
    }
    elsif ($result > 0 || $result == -2) {
        say "あなたの負け";
    }
}

実行例

$ perl janken.pl
数字を入力してください。
1: グー, 2: チョキ, 3: パー,
> 2
あなた: チョキ
わたし: パー
あなたの勝ち
> 1
あなた: グー
わたし: グー
あいこ
> (省略)

シンプルなコードですが,自分が入力を行うまで相手が何を出してくるかわからないこのしくみは,どこか人間の好奇心を根本から刺激するようなおもしろみを感じさせます。あるとき,これを筆者が以前から取り組んでいた英単語の暗記学習に活かせないかと考えて作ったのが,英単語学習ゲームcarvoです。

使い方

ターミナルでコードを実行すると,pecoのUIUserInterfaceで学習コースを選択する画面が現れます。

学習コースの選択画面

QUERY>
sample1
sample2
sample3
exit

ここで好きなコースを選択すると,コマンド選択画面に移動します。

sample1を選択した場合

Welcome to the "sample1"
You can choose a number from 1-31

play   ――(1)
again
card
exit   ――(2)
list
fail
voice
help

この画面から,選択ツールとしてchoが使われています。⁠J]キーまたは[K]キーで上下に移動してコマンドを選択します。play(1)を選択するとゲームが始まり,次のように英単語と5つの和訳候補が現れるので,英単語に該当すると思う選択肢を選びます。

expect
- ~を推測する
- ~を提案する
- (~に)頼る
- ~の特徴を述べる
- ~を予期する
- [Give up!]

選択が正解ならポイントが加算され,不正解なら間違えた単語が誤答リストに加わります。終了するには,コマンド選択画面でexit(2)を選択します。

小さなコードの積み上げ方

carvoはじゃんけんゲームと同様,while文を中心とする単純な構造のプログラムなので,初めは1本の小さなファイルに収まっていました。しかしそのうち,単語リストをYAMLファイルで管理したくなったり,機能ごとにファイルを分割したくなったりと,手を入れるたびに新しい書き方を試したくなり,結果的に今回紹介した中で最も行数が多いプログラムになりました。

コードの量が多くなれば,たとえ小さな変更でも想定外の影響が生じる可能性が高くなり,手を入れることが難しくなっていきます。このような状況に対して,筆者は普段からコード片を検証するためのファイルを1本用意しておき,そこで事前に動作を確認するようにしています。

sandbox.pl

my @arr = qw(apple orange lemon);        
say scalar @arr;                         |(1)
say $#arr;                               
__END__   ――(2)
my $foo = "abc";            
$foo =~ s/a(?=b)/x/;        
say $foo;                   |(3)
$foo =~ s/(?<=b)c/x/;       
say $foo;                   
__END__
my @foo = qw(apple lemon);   
my @bar = (@foo, @foo);      |(4)
say for @bar;                
__END__
(省略)

このファイルで扱う内容はさまざまです。配列の要素数を知るにはどうすればよいのか(1)⁠,正規表現の先読み/後読みはどう書くのか(3)⁠,配列の要素として配列を使うことはできるのか(4)など,些細ながら認識が曖昧だった部分を確認するために,以前に書いたコードの上に__END__(2)を挿入して,その上に最小のコードを書いて実行します。

__END__はその下にあるコードを一括でコメントアウトしてくれるトークンです注3⁠。この1行を入れるだけで,その下に書かれた以前のコードを消すことなく無効化してくれるので,筆者はこれを重宝しています。

こうして事前に挙動を確認してから本番のコードに手を入れるようにすると,想定外のエラーを減らすことができます。筆者はターミナルでpと打てばこのファイルが立ち上がるようにエイリアスを設定しています。

.bashrc

alias p='open path/to/sandbox.pl'
注3)
実際にはコードを無効化するだけでなく,冒頭で紹介した__DATA__と同様のしかたで__END__以下のデータにアクセスすることもできます。詳しくは公式ドキュメント「perldata - Perlのデータ型」より特殊なリテラルを参照してください。

<続きの(3)こちら。>

WEB+DB PRESS

本誌最新号をチェック!
WEB+DB PRESS Vol.126

2021年12月24日発売
B5判/168ページ
定価1,628円
(本体1,480円+税10%)
ISBN978-4-297-12539-4

  • 特集1
    開発環境から本番環境まで一気通貫!
    実践コンテナ活用
    VS Code,Docker,Kubernetes,Azure
  • 特集2
    iOS 15開発最前線
    Swift 5.5,UI開発,通知管理,Xcode Cloud
  • 特集3
    作って学ぶ検索エンジンのしくみ
    Goで実装! 膨大な情報からどう高速に探すのか