2008年11月06日

[Perl]リファレンスの使い方(サブルーチン編)

 備忘録を兼ねて、Perl5での無名サブルーチンのリファレンスの作り方と使用法。
 ChildTreeで「やっぱflock使えるなら使いたいよね」とか思いつつソース追ったらflock関数使ってない……。
 そんなわけで(まだ)ソースを書き換えているんですが、一部「ロック」→「ファイル読み込み」→「ロック解除」→「処理」→「ロック」→「ファイル書き込み」→「ロック解除」でロックが分断されるところがあるんですよ。処理している間に新たな書き込みがあったら、先に処理していた方が反映されなくなってしまいます。で、そんな部分がいくつかあってみんな処理が違うと。ちまちま書いていけばいいんだけど、ディレクトリトラバーサル対策のファイル名チェックとか色々やっているわけですよ。同じような処理はサブルーチンにまとめたいというわけで、異なる処理を引数にしてサブルーチンに投げてしまえってことです。(ファイルロックについては とむねこのページ > Web&Mail&Mac講座 > Perlの排他制御も参照)

 実は、サブルーチンもリファレンスにしてスカラー変数に代入することができます。
$ref = \&kansu;
↑こんな感じ。

 更に、リファレンスする段階でサブルーチンを定義することもできます。
$ref = sub { ...処理内容... };
subの後にブロック({})で処理内容を書きます。末尾のセミコロンを忘れないように。
$refにはこの名前がないサブルーチンのリファレンスが入っています。そう、名前がないから無名サブルーチンです。

 実際に無名サブルーチンの内容を実行したくなったら、デリファレンスします。
 &$ref;
 &$ref(1,10,100);
↑引数を渡すこともできます↑
グローバル変数もきちんと機能するようです。


というわけでテストコード。

#!/usr/bin/perl

use strict;
use warnings;

our $sp = 1000; #グローバル変数だよ
my($a,$b,$c) = (1,10,100);

## $ref_srに無名サブルーチンのリファレンスを代入するよ
my $ref_sr = sub {
my($x,$y,$z) = @_;
my $res = $x+$y+$z+$sp;
$sp = 999; #グローバル変数をいじくってみた
return($res);
};

&prtxt($ref_sr,$a,$b,$c);

print "グローバル変数は1000から$spに変わったよ\n";
exit;

## 表示するルーチン
sub prtxt{
my($ref,$i,$j,$k) = @_;
print "無名サブルーチンを作成して値渡しを試してみる\n";
print "無名サブルーチンのリファレンスに引数とグローバル変数が渡っていれば\n";
print "結果は1111になるはず。\n";
print "さて、結果は...";

## ここでリファレンスをデリファレンスして
## 引数を与えて結果を受け取って更にprintしているよ
print &$ref_sr($i,$j,$k);
print "\n\n";
return();
}


そんでもって実行結果。


無名サブルーチンを作成して値渡しを試してみる
無名サブルーチンのリファレンスに引数とグローバル変数が渡っていれば
結果は1111になるはず。
さて、結果は...1111

グローバル変数は1000から999に変わったよ


いい感じ。
タグ:Perl
posted by 鯖缶 at 22:57 | Comment(0) | TrackBack(0) | ただいま開発中 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバック
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。