はじめに
以前、perlのdo{}while実装をした時に変数スコープでつまづいたことを思い出しながら記事に残していこうと思います。また、前々から記憶の取り出しが苦手だなーと思っていたので、今回からちょこちょこコーネルメソッドを意識して書いていきたいなと思っています。
(コーネルメソッドについてはぜひ調べてみてください)
Cue
Perlのdo{}while実装時に変数スコープでつまづいたことは?
Note
perlのdo{}whileについて
- 一度は必ず関数内の処理が実行され、その後にwhile条件の評価がされる。
- whileの条件が一番最後に来るので、少し可読性が落ちる...ような気がしています。
- また、last, nextなどの機能が正しく働かない場合もあるので非推奨としているサイトもある。(いつもお世話になっているperlゼミさん)
do{}while関数、evalの変数スコープ
- 変数
$result
はdo{}whileブロック外で宣言しないと、スコープ外のためwhileの評価の時に参照できない。このため、$result
はdo{}while関数の外で宣言する必要がある。 - evalブロックで宣言された変数
$commit_result
もeval外で参照不可。このため$commit_result
はeval外で宣言する必要がある。
do {
eval {
my $sql = "SELECT name FROM $table_name WHERE delete_flg = 0";
my $result = $self->db->executeSql($sql);
my $commit_result = $self->db->commit();
};
if ($@) {
$self->logger->fatal("Execution Error: $@");
die "Cannot get data from $table_name\n";
}
#ERROR $commit_result
if ($result < 0 || $commit_result < 0) {
$self->logger->fatal($self->db->getErrMsg());
die "Cannot get data from $table_name\n";
}
#ERROR $result
} while ($result > 0);
解決方法
my $result;
my $commit_result;
do {
eval {
my $sql = "SELECT name FROM $table_name WHERE delete_flg = 0";
$result = $self->db->executeSql($sql);
$commit_result = $self->db->commit();
};
if ($@) {
$self->logger->fatal("Execution Error: $@");
die "Cannot get data from $table_name\n";
}
if ($result < 0 || $commit_result < 0) {
$self->logger->fatal($self->db->getErrMsg());
die "Cannot get data from $table_name\n";
}
} while ($result > 0);
Summary
- evalブロック内で宣言した変数は、外から参照することはできない。
- do{}while関数は必ず一回は実行され、最後に評価が行われる。また、評価に利用される変数はdo{}while関数外に宣言する必要がある。
最後に
普段あまりdo{}whileを使う選択をしないので、変数のスコープなど再度意識する良いきっかけになりました。
参考になれば幸いです🍏
参考