sironekotoroの日記

Perl で楽をしたい

すぐわかる オブジェクト指向 Perl 第11章 オブジェクト クラスの作成

-> は左結合

  • なるほど
  • $space = Triangle->new(3,4,5)->InscribedCircleSpace;
    • この場合には、Triangleメソッドに 3 , 4 , 5 って値を与えて三角形オブジェクトを作成して、その内接円を求める
    • おぉ、なんかかっこいい

!?

一方、クラスは型のことです。
少年漫画「翔丸」(能條純一著、講談社刊)では、さっきまで無軌道に暴れていた怖いお兄さん達が、謎の美少年・翔丸によってナイフで傷を付けられる事によってすっかり型にはめられてしまい、軒並み「翔丸組」の軍門に下ってしまいます。

  • いきなりの能條画伯の登場にビビる
    • 次のページにワンカットもある
  • こんな展開を550ページの本の350ページまで隠しておくとは・・・
  • 翔丸 - Wikipedia

    翔丸』(しょうまる)は、能條純一による日本の漫画。『コミックモーニング』(講談社)において1987年13号から1989年6号に掲載された。当初は不定期掲載、のちに隔週連載。同じく能條の『天の男』や『ゴッドハンド』に見られる「悪のカリスマ」を描いた系統の作品である。

  • 知らないなぁ・・・
    • 絶版本を置いているマンガ図書館Zには無かった。漫画喫茶ならあるかな?

ここでは「翔丸組」がクラスで、翔丸が振るうナイフがコンストラクタと考えられるでしょう

  • わかんねぇ・・・けど、分かるような・・・
  • ナイフでシャってやる事でクラスを作る、的な?

クラスとオブジェクトの関係はよく人形焼きに例えられます。人形焼きというと鯛焼きとかペコちゃん焼きの仲間で、皮とアンコを型に入れて焼くと、中から七福神などの形をしたお菓子が出てきます。
ここで人形焼きを作る機械をコンストラクタ、いっこいっこの人形焼きをオブジェクトというわけです。

オブジェクトは、あるクラスのコンストラクタによって、そのクラスのオブジェクトとして生成される

  • ううん、わかったような。
  • 鯛焼きは、鯛焼き機によって、鯛焼きになる・・・?んん?

# クラスとインスタンスとオブジェクト

クラスもまたオブジェクトである

  • なるほど、先の「鯛焼きは、鯛焼き機によって、鯛焼きになる」で??ってなったのは、こういうことか?

クラスがオブジェクトに与える要素のことをプロパティ(property 属性)といいます

メソッドは、オブジェクトに渡すメッセージであるという言い方をしましたが、メソッドには2つの目的があります。 - プロパティを取得する - プロパティを設定する

  • おっけー、これは分かる。

三角形型の操作も同じ原理です。「三角形さん、あんたを 3 , 4 , 5 という辺の長さで生成するよ」というコンストラクタメソッドの一種で、1つのメッセージ渡し(message passing) です。

  • うん、わかる、納得できる。

bless で classに神の祝福を

  • いろんなところで見てきて、いろんな本で見てきた bless が何をするものなのか、やっとわかった

    • インスタンスメソッドで作ったリファレンスが、どのクラスに属しているかをリファレンスに分からせる・・・
    • ちゃんとした言葉で言えないところに理解力不足を感じる
    • でも、分かった感はある、Perlオブジェクト指向の勉強してはじめて、分かった感がある。
  • ためしに、「続・はじめてのPerl」のOOPのところをさらっと読んでみると、わかる。

    • ただただ本を写経していたけど、今は、その意味が(なんとなく)わかる。
    • ここで、「続・はじめてのPerl」に行きたい気持ちを抑えて、本書を続行する。
    • というか、自作のオブジェクト作ってみたいすぎて

ゲッター、セッター

  • はい、これもイミフな単語でした。
    • はじめて聞いたのは、たしか YAPC::Asia2013 でだった気がする
    • よくそんなんで参加したなと思うが、参加したおかげで今があるので、積極的に参加するべき
  • オブジェクトのプロパティ?「直接いじれば良いじゃん」とか思ってたので反省。

    特に重要なのは、セッターで不法な値を代入したときに croak することです。

唐突に

  • あぁ、そうか、オブジェクトがデータと手続き(操作)を一緒に持ってるって、こういうことか
  • エウレカエウレカ

すぐわかる オブジェクト指向 Perl 第10章 静的クラスの作成

9章はみるだけー

  • 9章で参考にしている Calender というモジュールが CPAN からダウンロードできないみたいなので、見るだけ。

やってきましたオブジェクト指向

  • 構造化プログラミングで再利用部分をサブルーチンにくくりだす:ok
  • 再利用部分をファイルで分けて、モジュール化する:ok
  • ファイルをまたいで、サブルーチンを呼び出す:ok
    • &package名::subroutin(@ARGV)
    • 受け側には 引数(@ARGV) だけがわたる
  • メソッド呼び出し:ok
    • package名->subroutin(@ARGV)
    • 受け側には、パッケージ名と@AGRV がわたる
    • 矢印記法で呼び出されたサブルーチンをメソッドと言う
    • メソッドを持っているパッケージをクラスという
    • パッケージ名は第一引数となり、これをインボカント(invocant)、呼出し元という
      • 呼び出すは invoke
  • クラスの継承
  • AUTOLOAD
    • 継承元をさかのぼってもメソッドが見つからなかった場合にカバーしてくれる
    • 存在しないメソッドの完全修飾名が $AUTOLOAD に入る
    • サブルーチンの実装忘れもこれで安心(違
  • 継承されるのはメソッドだけ
    • 変数は継承されない
  • use base qw(package) 、1モジュール1パッケージでスッキリ
    • あまり複雑な事はしないようにしよう・・・
  • is a
  • SUPER クラス

正直なところ

  • 継承とオーバーライドについてはok
  • でも、is a とかについては実際に使えるんかな、って気がする。
  • 正直、メソッド呼び出しをしてパッケージ名がサブルーチンに渡されるメリットが分からない。
  • 以上が今の到達地点
  • とりあえずこのまま進めて、分からなかったらまた戻ってこよう。

すぐわかる オブジェクト指向 Perl 第8章 モジュールを使う use

モジュールのバージョン

  • @EXPORT$VERSION 変数を指定しておく事でモジュールが use した時のチェックを行う事が出来る、と
  • モジュール側で
package hogehoge;
our @EXPORT = qw($VERSION);
our $VERSION = "1.0";

としておいて、呼び出し側はこう

use hogehoge 2.0;

とするとエラーになる

おなじみ use

  • use strict よく使うというか必須だよね
  • しかし、そこで何をしているかは考えた事も無かった・・・

    use モジュール名;
    という1つの文は、次の4行のプログラムと全く同じ動作になります。
    BEGIN {
    require モジュール名;
    import モジュール名;
    }

  • なるほど

  • つまり use はモジュールを読み込んで、さらにモジュール内の変数やサブルーチンを import すると
    • そのまんまやねん

うなる

変数は my をつけてレキシカル変数にする事で完全にプライバシーを守れ、モジュール外から見る事ができなくなりますが、サブルーチンだけは完全修飾名を使う事でモジュール外から見る事ができてしまいます。では、モジュール外からアクセスできないサブルーチンを定義する事はできるでしょうか?

答えは、できます。ちょっと難しい話ですが、ここまでの知識で答えられるのでちょっと考えてみてください。
はいおわかりですか。無名サブルーチンリファレンスを使って、それをmy変数に代入すれば良いですね。
これをプライベートメソッドと言います。

  • なるほど!

すぐわかる オブジェクト指向 Perl 第6章 、第7章

第6章 ライブラリを取り込むrequire

なるほど

  • リストの要素である、数字の重複を排除する、というサブルーチン uniq
my @arr = ( 5, 4, 7, 4, 5, 7, 4, 3 );

sub uniq {
    my @in = @_;
    my %out = ();
    foreach my $in (@in) {
        $out{$in} = 1;
    }
    my @return = keys %out;
}

print uniq(@arr); #4375
  • 配列をハッシュの key にして、その値に固定値で1を入力する。
    • よくある
    • でも、プログラムを学ぶ前だと分からなかったと思う。
    • 準備された uniq 関数を使う事は出来ても、それを自分で実装できたかどうか・・・自信ない

「なんでもかまわない時は1」というのは Perl 仲間の間で、ゆるやかな合意として成立しているので、他の人がリストを読んだとき「ああ何でもかまわないから1を入れたんだな」とわかります

  • この「1」ってのは、モジュール作ったときに最後に入れる「1」と同じなんかな?
  • おいおい出てくるだろう

ライブラリ

次に arrUtil というライブラリを作っていきます。ここでライブラリ(library)とはサブルーチンを集めて色々なプログラムで呼び出せるようにするファイルの事です

  • ライブラリの説明って以外と無かった気がする。
    • もちろん、うちが覚えていないだけの可能性大

小ワザ

print join "\n" , @INC;
  • ライブラリがおいてあるフォルダを表示するものなんだけど、なるほど、join をこうやって使うのか、と。
    • うちだったら、配列だから foreach つかって〜・・・ってなってたと思う。迂遠
  • そして @INC の中に、 . があるから、カレントディレクトリ内のファイルもライブラリとして実行できるんね

第7章 名前空間を作るパッケージ

  • my で変数を宣言する、という事がその変数の呼び出せる範囲を規定する事、つまりオブジェクト指向における「カプセル化」を担う・・・
  • なるほどなぁ!何も考えずに、マナーとして my を使ってきたんだけど、なるほど。
  • だもんで、 our で宣言する変数の使い道?とかよく分かってなかった。
  • いやー、勉強になる!勉強してるんだから当然だけど、勉強になる!

すぐわかる オブジェクト指向 Perl 第4章 、第5章

ハッシュスライス!

  • 「第4章 ハッシュのリファレンス」については特に引っかかりなくすらすらと
  • いや、一個だけあった、ひっかかったところ
$refMonth = {
    January   => 1,
    February  => 2,
    March     => 3,
    April     => 4,
    May       => 5,
    June      => 6,
    July      => 7,
    August    => 8,
    September => 9,
    October   => 10,
    November  => 11,
    December  => 12,
};

for( @{$refMonth}{ September, October, November } ) {
    print "autumn contains month No. $_\n";
}
  • @{$refMonth}{ September, October, November } 、普段ハッシュスライスを使わないので、初見で???だった
    • ハッシュスライスを使うべきところで、迂遠な書きかたしているなぁって思った
    • 知っていれば回避できる苦労、知らないと回避できない苦労
    • 学習大事よね

サブルーチンリファレンスがあるなら、サブルーチンは

  • 「第5章 サブルーチンのリファレンス」
  • サブルーチンもリファレンス化出来るなら、普通の(今まで学習してきた)サブルーチン構文とはいったい・・・って気持ちに
    • サブルーチンのみならず、(普通の)配列も(普通の)ハッシュも、リファレンス化したものの前座なのだろうか・・・

シグナルハンドラ

ここでは Perl であらかじめ定義された特殊なハッシュ変数 %SIG というものを紹介します。この要素にサブルーチン リファレンスを入れると、プログラムが OS の機能によってあるシグナルを受け取ったときに、そのシグナルによってサブルーチンを実行します。

  • $SIG{'INT'} = sub {print "Oh, you pushed Ctrl-C! \n"}
    • Ctrl + C を押したときに、 `SIG{'INT'} が呼び出されて、そのときハッシュの値に格納されたサブルーチンが動く、という理解で良いのかな?

この行では、ハッシュ要素 $SIG{'INT'} に無名サブルーチンを代入しています。これによって、このプログラムが sigiht をもらったときに実行する動作を定義しています

  • 通常は Ctrl + C でプログラムの実行を止める sigint になるけど、その動きを上書きして制御できると。
  • なるほど!

シュワルツ変換

  • まず名前がかっこいい
    • 大昔、シナリオシュミレーションゲームで「シュバルツシルト」ってゲームありましたなぁ
  • たしか「続・はじめてのPerl」にも出てきた
  • その時はふんふん、なるほどーで通り抜けた程度
  • しかしこの本はみっちり解説がついている
  • 詩を、各行の長さ順で並べ替えるという例題
    • その1:各行の文字列の長さを配列に入れ、それを sort
my @input = <DATA>;
my @length = ();

for (@input){
    push @length , length($_)
}

print sort {$b <=> $a} @length;
  • その2:各行そのものの文字列と、文字列の長さを配列に入れて、リファレンス化し、それを別な配列に入れる
for (@input) {
    my @lengthIndex = ();
    $lengthIndex[0] = $_;         # 文字列そのものを配列の0番目に
    $lengthIndex[1] = length($_);   # 文字列の長さを配列の1番目に
    push @length, \@lengthIndex;
}
  • その3:(その2で用意した)配列リファレンスを、文字列の長い順に並べ替えて、さらに別な配列に格納
    • 一応これで例題は解ける
my @length2 = sort {$b->[1] <=> $a->[1]} @length;
for (@length2){
    say $_->[0];
}
  • その4:最初の for 内で利用している配列を無名配列にする

    • なるほど、確かにこの @lengthIndexfor の中でしか使っていない、「使い捨て」の配列だ
    • これぞ無名配列!これこそanonymous Array !納得した!
  • その5:2回使われている foreachmap で置き換えていく

my @length = map { [ $_ , length($_) ]  } @input;
my @length2 = sort { $b->[1] <=> $a->[1] } @length;
print map {$_->[0]} @length2;
  • その6:mapUNIX のパイプのように書けるので、中間配列が不要になる
    • ついでに不要なコードブロックも外す
print map $_->[0], 
      sort { $b->[1] <=> $a->[1] }
      map [ $_, length($_) ], @input;
  • 美しいなぁ・・・

すぐわかる オブジェクト指向 Perl 第3章 配列のリファレンス

わかる

  • いきなり引用

ここで、2つの配列 @tanka と @kosuu を渡すと、売り上げ金額の合計を返すサブルーチン &uriage を考えてみます。
サブルーチンの中身を書く前に、メインのプログラムでこのサブルーチンを呼び出す方法を考えてみます。
&uriage(@tanka,@kosuu)
でしょうか。いや、ここでこれがいきなりダメです。
というのは、サブルーチンの引数は、サブルーチンの内部で
@_
という配列に入るのですが

  • ガッテンガッテン!
  • なるほど、そうか、そりゃそうだ
  • サブルーチンの引数に配列そのまま突っ込むとダメ、展開されちゃうってのは知ってたけど、 @_ に入れるからか、そうか、改めて説明されるとそうか、そりゃそうだ

2つ以上の配列をサブルーチンに渡す

やる気とお時間があればここでいったんしおりを挟んで本を閉じ、ご自分で書いてみてください

  • 学習本において、こう書かれていたら、やってみなくては実力が付かない
  • 自分が最初に書いたもの
sub uriage {
    my ($ref_tanka , $ref_kosuu) = @_;
    my @tanka = @$ref_tanka;
    my @kosuu = @$ref_kosuu;
    my $sum;
    foreach my $soeji (0 .. $#tanka){
        $sum += $tanka[$soeji] * $kosuu[$soeji];
    }
    return $sum
};
  • 途中の
    foreach my $soeji (0 .. $#tanka){

    foreach my $soeji ($#tanka){
    って書いて事故った。
  • 同じ要素数の配列なので、配列のインデックス順に2つの配列にアクセスしていけば良いという考え
  • 本に載ってたのはこちら
sub uriage {
    my ( $ref_tanka, $ref_kosuu ) = @_;
    my $uriage = 0;
    foreach my $tanka (@$ref_tanka) {
        my $kosuu = shift @$ref_kosuu;
        $uriage += $tanka * $kosuu;
    }
    return $uriage;
}
  • shift をそう使うのか!なるほど
  • for ブロックの中で配列(のリファレンス)を操作するのか
  • デリファレンスした配列をそのまま foreach に入れるのか

  • いろんなやり方見るの楽しい。

    • 短いプログラムですぐに理解できるようなものなら、なお楽しい

濃いなぁ

  • 先の2章があっさりだったが本章は濃い
my @month = qw/january february march april may june july august september november deccember/;

$refMonth = \@month;

print "refMonth: $refMonth -> @$refMonth" , "\n" , "No.5 : $$refMonth[4]";
  • スカラーデリファレンス・・・?

    • 配列の要素はスカラーだから間違いではないか

    $refMonth のリファレントを配列としてでリファレンスしたものに、 [4] をインデックス付けしたもの

  • Perlエンジンの名前の解釈の仕方

    • 名前を見つけたら、その前を見る: $$refMonth[4] の 'refMonth' が名前、その直前だと $ ($$の内側、後ろの方)
    • 記号 $ を解決する。すなわち $refMonthスカラー
    • さらに、前に記号 $ がまだあるので、それを解決。 $$refMonthスカラーへのリファレンス
      • 先の2章で「役に立たない」と言われていたスカラーのリファレンスじゃないすか
    • 前には記号がもうないので、名前の後ろを解釈していく
    • [4] は配列の5番目の要素(0はじまりだから)、つまりリファレント(参照先)は配列と判断
    • 後ろにはもう何もない。解釈終了。
  • Perl の気持ち

$$refMonth[4]${$refMonth[4]} の違い

  • $$refMonth[4] はリファレンス化した配列の4番目のインデックスの要素
  • ${$refMonth[4]} は・・・
    • {} コードブロックで分けてあるので、そこまでの処理で一度とまる
    • スカラー $refMonth
    • コードブロックあるから、後ろを見る
    • 配列の5番目を示すスカラー $refMonth[4]
      • @refmonth の 5番目?
    • $refMonth[4] の要素をデリファレンスしたもの?つまり、リファレンスが入っている?
my $rm1  = 'january';
my $rm2  = 'february';
my $rm3  = 'march';
my $rm4  = 'april';
my $rm5  = 'may';
my $rm6  = 'june';
my $rm7  = 'july';
my $rm8  = 'august';
my $rm9  = 'september';
my $rm10 = 'october';
my $rm11 = 'november';
my $rm12 = 'december';

my @refMonth = (
    \$rm1, \$rm2, \$rm3, \$rm4,  \$rm5,  \$rm6,
    \$rm7, \$rm8, \$rm9, \$rm10, \$rm11, \$rm12
);

print ${$refMonth[4]}; # may
  • 配列 @refMonth の5番目に入っているスカラーのリファレンス
    • わかるかぁっ!
      • 書いてみると分かる
  • 苦しい、こうやって解釈していくの苦しい。慣れるもんなんだろうか。

すばらしい「ぶつぶつコンンピュータ」

  • この章、配列のリファレンスを1行ごとに解説する「ぶつぶつコンンピュータ」、つまりPerlを実行するコンピュータの気持ちになってリファレンスを紐解いていく下りがあるんだけど、これが良い
    • くどいけど良い
  • うちのような初学者には、これが本当に理解の助けになる。
  • 例えば、 $month->[2][0] ってリファレンスについて
  • month という名前があるなー
  • 前に $ があるからスカラーだなー
  • 後ろに -> があるから $month はリファレンスだなー
  • $month->[2] ということはリファレントは配列で、その第3要素を返せばいいなー(配列インデックスはゼロ始まりだからなー)
  • さらに [0] があるから、 $month は別の配列へのリファレンスで、そのリファレントの第1要素を返せばいいなー
  • これを追体験していく事で、ほんと理解が深まるんだよなぁ。
  • 全編これだと本のサイズがふくれあがっていくらページあっても足りないし、くどいけど

無名感、即時感

  • 無名配列、書いてはいるので、何となく分かる
  • 分かるけど、どう、「無名」なのかがずっと引っかかっている
    • アクセスするときは配列名がないため、リファレンス通しており、リファレンス名は配列名ではない・・・ってのは分かる・・・よ
  • anonymous っていうと、今時だとあのガイ・フォークスの仮面思い出しちゃう

  • そこに(勝手にうちがメンターとして仰ぎ見てる)@xtetsujiさんが助け舟を

  • 無名感!即時感!こっちの方がしっくりくる。なるほど。
    • Javascript で「無名関数」を「即時関数」って言ってる本があったなそういえば
    • いちいち配列名をつけず、そのまま配列作ってしまう即時・即席感

すぐわかる オブジェクト指向 Perl 第2章 「参照」は小粒でピリリと辛い 〜 スカラー リファレンス 〜

スカラーリファレンスで1章まるまる?

  • リファレンスについては「どういうものか」は分かるんだけど、スカラーリファレンスって使い道あるんかな・・・?
  • という疑問を持ちつつ本を読んでいく

今の時点で理解している「リファレンス」

  • 変数がおさめられているメモリ上の番地
  • 配列やハッシュもリファレンスにするとスカラーとして扱う事が出来る
  • 配列の中に配列、ハッシュを入れる事は出来ないが、スカラーなら入れられる
  • だからリファレンスにしてスカラーにする事で、配列の中に(リファレンス化した)配列やハッシュを入れる事が出来るようになる
  • リファレンス化した配列やハッシュを元に戻すには「デリファレンス」を行う

!?

$refAge = \14;

print "refAge is $refAge and it contains $$refAge \n";
# refAge is SCALAR(0x7fddf201ad10) and it contains 14

$refName = \"Robin";

print "refName is $refName and it contains $$refName \n";
# refName is SCALAR(0x7fddf201ae78) and it contains Robin
  • $refAge = \14 こんな書き方も出来るのか
    • メモリ空間に直接数値を入れ、そこへのリファレンスが生成されると

スカラー変数のリファレンスはあまり役に立たない

  • ですよねー
  • 次章以降の配列、ハッシュ、サブルーチンリファレンスが楽しみ