ついにPerlでオブジェクト指向

ついにいよいよ、という感じでPerl入学式第5回の後半、オブジェクト指向な感じの部分に入ってみます。

資料はこちら。
https://github.com/perl-entrance-org/workshop-2013-05/blob/master/slide.md#package--%E5%90%8D%E5%89%8D%E7%A9%BA%E9%96%93

まず、「package / 名前空間」という項目について。ぐぐーっと、説明を読んでいきます。
ぐぐー・・・・・っ。

はい。で、練習問題がありましたので、トライします。
https://github.com/perl-entrance-org/workshop-2013-05/blob/master/slide.md#%E7%B7%B4%E7%BF%92%E5%95%8F%E9%A1%8C-2

  • PerlEntranceというpackageの中にtokyoとosakaという名前の, 引数を持たないサブルーチンを作りましょう
  • tokyoはpapix!!!, osakaはboolfool!!!という文字列を返す機能を持たせましょう

作ってみました。

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

package PerlEntrance {
    sub tokyo {
        print "papix!!!\n";
    }
    sub osaka {
	print "boolfool!!!\n";
    }
}

PerlEntrance::tokyo();
PerlEntrance::osaka();

実行結果はこんな。

papix!!!
boolfool!!!

はい。よさそうですね。(たぶん)

次。モジュールの話がしばらく続きます。ふむふむ・・

作業場所の構成の話なども出てきます。

作業ディレクトリ
 |- plactice.pl # モジュールを実行するスクリプト
 |- lib
    |- PerlEntrance.pm # モジュール本体     
  • このような構成でフォルダとファイルを作ります
  • Perlのスクリプトの拡張子は*.plですが, モジュールの場合は*.pmにします
  • PerlEntrance.pmの中に, 先ほどの練習問題で書いたコードから, 実行する部分を取り除いたものを書いておきます
  • さらにPerlEntrance.pmの末尾に1;とだけ書かれた行を追加してください

なるほど。で、そのまま説明を読み進めると、

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

use PerlEntrance;

print PerlEntrance::tokyo(); # => papix!!!
print PerlEntrance::osaka(); # => boolfool!!!
  • practice.plをこのように書くと, PerlEntrance.pmに書いたサブルーチンを使えるようになります
  • ただし, 実行時はperl -Ilib practice.plのように起動してください
  • package名とモジュール名(ファイル名)は, 同じ名前にすることが多いです

とあるので、そこまで含めてやってみました。

具体的には、僕の場合は、ホームディレクトリの中に「Homework」というディレクトリを作成して、さらにそこにpractice.plとlibディレクトリを、そしてlibディレクトリの中にPerlEntrance.pmを作りました。
practice.plは上記内容のママ。PerlEntrance.pmは、最後にあった実行命令2行をカットして、代わりに「1;」を加えてこんな感じ。

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

package PerlEntrance {
    sub tokyo {
        print "papix!!!\n";
    }
    sub osaka {
	print "boolfool!!!\n";
    }
}

1;

・・が、実行結果はこんな。

papix!!!
1boolfool!!!
1

ん〜〜、この、「boolfool!!!」の前後にそれぞれ入ってる「1」って、たぶん.pmの最後に加えた

1;

ですよね。でも、そんなのが出てくるとは資料には書いていないし、けっこう時間をかけてぐぐったのですがそういう問題に直面している人もなし・・なんでだろう・・??

ま、とりあえず、その「1」が入ってしまうことについては一旦判断保留(エポケー)して、続いて練習問題があったので、そちらをやってみました。

  • PerlBeginnersというモジュール/packageを作ってその中にperllevelというサブルーチンを作りましょう
  • perllevelは1から10の整数の引数を取ります.

なるほど。資料の説明に沿って、こんな感じにしてみました。

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

package PerlBeginners {
    sub perllevel {
        my $level = shift;
    }
}

1;

んで、それを受けての練習問題がこちら。
https://github.com/perl-entrance-org/workshop-2013-05/blob/master/slide.md#%E7%B7%B4%E7%BF%92%E5%95%8F%E9%A1%8C-4

use PerlBeginners;
print PerlBeginners::perllevel(1);
# =>
# レベル1: Perl 関係の書籍や資料を何も読んでいない。Perl がプログラミング言語だということは知っているが、それ以外のことは何も知らない。他人の書いたPerl プログラムを実行できるので、プログラムの一部を編集することでプログラムの動作の一部(出力される文字列の内容など)を変更できることを知っている。プログラムのほかの部分に変更を加えてもなぜうまくいかないのか理解していない。この言語に合うメンタルモデルを持っていないので、Perl の構文をCOBOL とC++ のような他の言語のものとは区別できていない。
  • 引数をレベルと解釈して, 上記のように使います.
  • Perlレベルは以下のブログに掲載されているので何らかの形でモジュール内に保持しましょう.

はい。ということで、これを受けて作ったのがこちら。(Gistに上げました)

で、これをさっきのPerlEntranceと同じlibディレクトリに入れつつ、これを処理する.plファイルを「practice2.pl」として、これまたさっきの「practice.pl」と同じ階層に入れて、以下の内容で実行してみました。

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

print PerlBeginners::perllevel(5);

実行の仕方もさっきと同様、資料にあるとおりこんな感じで。

$ perl -Ilib practice2.pl

しかし、結果はこちら・・。

レベル5: 正規表現、演算子、I/O、およびスコープについて基本的な理解がある。皆が言っているので、my、use strict、およびuse warnings を使用している。多くの人たちがこのレベルを超えないのは、たとえ非効率であっても、再利用可能なコンポーネントの作成を除けば、ほどんど何でもできるからである。このレベルか次のレベルでは、リファレンスのことを知っている。
1

ん〜〜〜〜〜、惜しい? やっぱり最後に「1」が入ってますね・・これ違うんですよね、たぶん。

ここでいろいろさらにぐぐったり、手元の本をいくつか並べて見てみたんですが、packageとかモジュール作成においては、ちょっと書式が上記とは違って、先に

package PerlBeginners;

とか宣言してから、別個でサブルーチンを作ったりしているので、その書式が違うせいかなあ、とか思っていろいろ試したんですが、そういう問題でもなさそうで。
・・とはいえ、 まあ、けっこう考えても分からなかったので、再び判断保留して、次のお題目であります「テスト」に行ってしまいます。

https://github.com/perl-entrance-org/workshop-2013-05/blob/master/slide.md#%E3%83%86%E3%82%B9%E3%83%88

さらりとテストを書く

use Test::More;
use PerlEntrance;

is PerlEntrance::tokyo(), 'moznion!!!';

done_testing();
  • practice.plが置いてあるディレクトリに. plactice.tという名前で以下の様な内容でコードを書きます
  • そのディレクトリでprove -Ilib practice.tと実行してみましょう
    • どうなりましたか?

はい。やってみました。念のために言うと、僕の「practice.t」は、最初にstrictプラグマなどを加えて以下のようになっています。

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

use Test::More;
use PerlEntrance;

is PerlEntrance::tokyo(), 'moznion!!!';

done_testing();

で、実行!!

practice.t .. 1/?
#   Failed test at practice.t line 8.
#          got: '1'
#     expected: 'moznion!!!'
# Looks like you failed 1 test of 1.
practice.t .. Dubious, test returned 1 (wstat 256, 0x100)
Failed 1/1 subtests

Test Summary Report
-------------------
practice.t (Wstat: 256 Tests: 1 Failed: 1)
  Failed test:  1
  Non-zero exit status: 1
Files=1, Tests=1,  0 wallclock secs ( 0.06 usr  0.01 sys +  0.05 cusr  0.01 csys =  0.13 CPU)
Result: FAIL

ん、ん〜〜。何かまた違う・・。なんか実行結果の3行目で、

#          got: '1'

と返っていますが、ここって

#          got: 'papix!!!'

って返ってくるべきところなんですよね・・資料にはそう書いてあります。
https://github.com/perl-entrance-org/workshop-2013-05/blob/master/slide.md#prove

ここまで重ねて判断保留(というかスルー)してきた不明点がこんな形でまた戻ってくるとは・・やはり理解しないまま進むのって良し悪しですね・・
資料が違うのか、ぼくが説明を勘違いして受け取っているのか、よく分かりませんが。
ともあれ、ここがズレちゃうとその後の流れもグダグダになるので、今日はこの辺で寝ることにします・・

ちなみに、資料によると、テストでは

All tests successful.

と出ればみんなハッピー、ということになるようです。早くハッピーになりたい・・!!

#コメント欄にて進捗がありました。(てつじさん、ありがとうございます!)よろしければあわせてお読みください。
#補足記事も書きました。
http://note103.hateblo.jp/entry/2013/12/26/225055