Perl入学式2013年度第6回補講・予習(Mojoliciousでfizzbuzzにハマった話)

前回参加したPerl入学式の話の続きがまだ終わっていないのですが、
http://note103.hateblo.jp/entry/2014/02/18/184136

今月末に予定されている第2期最終回の補講が一週間後に迫ってしまったので、とりあえず予習の方を優先しております。

最終回はおもにWAF(Webアプリケーションフレームワーク)のMojolicousを用いたアプリ作成がテーマということで、とりあえずその資料の内容を予習してみました。
https://github.com/perl-entrance-org/workshop-2013-06/blob/master/slide.md

基本的には資料をずーっと上から下へたどっていけば把握できるように作られているのですが(すごい)、以下のfizzbuzz問題でハマったのでちょっとその内容をさらってみたいと思います。
https://github.com/perl-entrance-org/workshop-2013-06/blob/master/slide.md#%E7%B7%B4%E7%BF%92%E5%95%8F%E9%A1%8C-1

  • fizzbuzzテンプレートを用意して, 1から100までのfizzbuzzを表示してみましょう
    • 但し, fizzbuzzの処理は全てfizzbuzzテンプレートの中に書くようにしましょう
  • fizzbuzz
    • 3で割り切れる場合「Fizz
    • 5で割り切れる場合「Buzz」
    • 3でも5でも割り切れる場合「fizzbuzz

ということで、まず超復習もかねて普通にfizzbuzzを作ってみます。

#!/usr/bin/env perl
use strict;
use warnings;

for my $str (1..100) {
    if ($str % 3 == 0 && $str % 5 ==0) {
        print "fizzbuzz\n";
    } elsif ($str % 3 == 0) {
        print "fizz\n";
    } elsif ($str % 5 == 0) {
        print "buzz\n";
    } else {
        print "$str\n";
    }
}

こんな感じでしょうか。実行したら大丈夫でした。

ちなみに、ぼくは最近この手のスクリプトを簡単に実行したいというとき、以前のこの記事でちらっと触れた、Quickrun.vimを使っています。
http://note103.hateblo.jp/entry/2014/02/11/005326

.plで保存したPerlスクリプトをQuickrunで実行すると、こんな感じで出てきます。

f:id:note103:20140323001251p:plain

ぼくはショートカットでノーマルモード中に<C-k>と押したら実行するようにしているので、大層便利です。

閑話休題。ではこれをMojolicious::Liteで作っていきます。
まず、ターミナルで以下。

mojo generate lite_app fizzbuzz.pl

最後の方、Perl入学式の資料だと拡張子は付いていませんが、ぼくの環境だと.pl付けておいた方がいろいろラクなのでそのようにしています。
※もちろんナイほうが良い場合は直しますが・・補講のときに時間があれば聞いてみるかも。

まだ何も書いていませんが、おもむろに実行しておきます。

morbo ./fizzbuzz.pl

このとき、「./」はなくても動くようですが、資料には付いているので、あったほうが良いのでしょうかね。これも聞けたら聞いてみたいですが。(補講で)

ではあらためて、fizzbuzz.plを触ります。
初期状態はこんな感じ。

#!/usr/bin/env perl
use Mojolicious::Lite;

# Documentation browser under "/perldoc"
plugin 'PODRenderer';

get '/' => sub {
  my $self = shift;
  $self->render('index');
};

app->start;
__DATA__

@@ index.html.ep
% layout 'default';
% title 'Welcome';
Welcome to the Mojolicious real-time web framework!

@@ layouts/default.html.ep
<!DOCTYPE html>
<html>
  <head><title><%= title %></title></head>
  <body><%= content %></body>
</html>

で、最初はこんな感じかなー、とやってみたのですが、

#!/usr/bin/env perl
use Mojolicious::Lite;

get '/' => sub {
  my $self = shift;
  $self->stash(title => 'fizzbuzz_practice');
  $self->render('index');
};

app->start;
__DATA__

@@ index.html.ep
% layout 'default';
% for my $str (1..100) {
%     if ($str % 3 == 0 && $str % 5 ==0) {
%=         print "fizzbuzz\n";
%     } elsif ($str % 3 == 0) {
%=         print "fizz\n";
%     } elsif ($str % 5 == 0) {
%=         print "buzz\n";
%     } else {
%=         print "$str\n";
%     }
% }

@@ layouts/default.html.ep
<!DOCTYPE html>
<html>
  <head><title><%= title %></title></head>
  <body><%= content %></body>
</html>

こんな感じになりまして・・

f:id:note103:20140323001338p:plain

ようは1が100個横並びになっている、と。
ここで勘の良い読者は「1?」とお気づきかもしれませんが、たぶんそのとおり、このブログで幾度となく登場した「あの1」という感じがします。
まあ、最初はぼくは全然わからなかったわけですが・・

ともあれ、まあ改行が反映されていないのは象徴的なので、indexのテンプレートをこのようにしました。

@@ index.html.ep
% layout 'default';
% for my $str (1..100) {
%     if ($str % 3 == 0 && $str % 5 ==0) {
%=         print "fizzbuzz";
<br>
%     } elsif ($str % 3 == 0) {
%=         print "fizz";
<br>
%     } elsif ($str % 5 == 0) {
%=         print "buzz";
<br>
%     } else {
%=         print "$str";
%     }
% }

すると今度はこんな結果に・・

f:id:note103:20140323001413p:plain

まあ、1が100行続く、みたいな感じですね。若干予想通りな感もありましたが。
で、結論的には以下のようにしたら、なんとかなってくれました。
(ひさしぶりにGistに上げました)
https://gist.github.com/note103/9705533

結果。

f:id:note103:20140323001423p:plain

はい。ええと、「fizzbuzz, fizz, buzz」の語については「%」も「%=」も「print " ";」も何も付けず、素の状態にして、最後の変数 $str だけ、%= を残しています。

資料を見た感じ&手元の木本さんの本(業務に役立つPerl)を読んだところでは、「%=」や「<%= %>」を使うと、Perlのコード(式や関数)を実行して、その結果をテンプレートに埋め込む、とあるので、

print "fizz\n";

とか

print "$str\n";

なども「%=」や「<%= %>」を使えばそのまま実行&表示されるものと思いましたが、そういうことではなさそうです。
この場合は多分、とくに最後の(26行目)

%= $str

あたりの実行のされ方が象徴的というか、そこが分かれば対応していけそうだな、とは思っていますが。

ということで、その後のBBSの作成もちらちらやってみましたが、ひとまずここまで。