プロが教えるわが家の防犯対策術!

Perlでmyを使う場合、サブルーチンの内外での宣言の違いについて知りたいです。
私はよくある変数をそのプログラム内全体で使う時(カウントするだけの$iみたいなものや、DBのクエリなど)は、同じ変数名をサブルーチン内で毎回宣言するのが嫌(個人的に同じことを重複するプログラムが好きではないという主義)なので、サブルーチンの外でmyを宣言するのですが、myとかはサブルーチン外で宣言するとどんな問題が生じる可能性があるのでしょうか?

また毎回サブルーチン内で宣言するのと外部で宣言するのではどういった時に問題になるのでしょうか?もちろんサブルーチンの外でmy宣言した場合はサブルーチンにその変数が引き継がれることは知っています。
リファレンス部分で変わるような記述を見たことはあります。

さしあたって問題を感じでいないのです、ふと疑問に思ったのですが、どうもそれに書かれたソースが少ないので御存知の方がいればぜひ御教授願いたいです。

<例>
my $hoge;
sub hoge1
{
$hoge = 1;
}
sub hoge2
{
$hoge = 5;
}



sub hoge1
{
my $hoge = 1;
}
sub hoge2
{
my $hoge = 5;
}

A 回答 (3件)

> カウントするだけの$iみたいなものや、DBのクエリなど



こういうのこそ、myでスコープ限定するべきものだと思うのですが。

例えば
my $i ;
for( $i = 0 ; $i < 20 ; $i ++ ) {
printf "before %4d:" , $i ;
printf "sum %4d:" ,&hoge($i) ;
printf "after %4d\n" , $i ;

}

sub hoge {
my $max = shift ;
my $ret=0;
for( $i = 1 ; $i <= $max ; $i ++ ) {
$ret += $i ;
}
return $ret;
}

こんなプログラム、実行したらどうなると思います?
# ちなみに、 my $max=..を削除して、$i<=$max を $i <= $_[0] にすると....

$iみたいな汎用的に使うループ変数は、逆に他に影響を与えてないか注意しないといけないものです。ですから、むしろ積極的にmy で範囲を限定するのが間違いが少ないです。
これくらいの規模ならすぐにわかると思いますが、規模が大きくなると、どれが使ってない変数だかわからなくなります。


独学とのことなので、今までは、Perlの文法やコマンド、関数等を学んできたのだと思います。
しかし、そういう「言語入門」的な書籍などでは、あまり「プログラミングスタイル」といったものは載っていないと思います。

ここらで、プログラミングスタイルについての勉強もしてみませんか?
とりあえずは「構造化プログラミング」をキーワードに本やサイトを探してみてください。
計算機工学の分野では古典の部類に入る考え方ですが、現在主流のオブジェクト指向等にもつながる基本的な考え方となっています。

> 同じことを重複するプログラムが好きではないという主義

これ自体はいい考えだと思いますよ。
ただ、それと、myを外に出す、というのはちょっと違うと思います。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
なるほど、構造化プログラミングというんですね。
さっそく勉強したいと思います。

forはあまり使いません(foreachやwhilleの方がメモリを食わないという記述をみたので…)その際に
sub hoge {
$i = 0 ;
foreach my $key( @hoge ){
$i++;
}
}
みたいな書き方を良くします。
とりあえず$i = 0 ;さえ書く習慣があれば変数自体は常に0から始まりますし…。。。

ただやはり個人的ななれなので他人から見るときっとわかりにくいソースになっているんでしょうね。
そういう意味ではやはり書き方を改めるべきですね。

お礼日時:2010/11/13 22:19

> 個人的に同じことを重複するプログラムが好きではないという主義


同じことを繰り返し書かないというのは良いスタイルですが、
今回の場合はやってることは同じではありません。

> sub hoge1
> {
> my $hoge = 1;
> }
> sub hoge2
> {
> my $hoge = 5;
> }

前者は「sub hoge1の$hogeを宣言」、後者は、「sub hoge2の$hogeを宣言」なので違うことをやっています。

これらは名前が同じだけで別の変数なので、外に出すなら
> my $hoge1_hoge;
> my $hoge2_hoge;
> sub hoge1
> {
> $hoge1_hoge = 1;
> }
> sub hoge2
> {
> $hoge2_hoge = 5;
> }
とでもしなければ別の変数になってくれません。
しかし、これは面倒ですし、何より無関係のサブルーチンから変数を操作される恐れがあります。
(間違って変数を操作した場合にどうなるかはNo.2の方が例示してくれてるので割愛。)

要するに、最初のようにサブルーチン内で宣言した方が楽ができるのです。
プログラミングするときは、できるだけ楽になるようにしましょ。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

すいません、hogeという例がよろしくないようですね。
こちらの説明不足でうまく伝わっていないようで…。

ソースを書くのが面倒なので割愛しますが、あくまでhogeはサブルーチン内で一時的に使う関数なのでおっしゃるような自称は起きないかとは思います。

できるだけ楽に書くというのはわかります。

お礼日時:2010/11/13 22:26

ちょっとした本 (例: らくだ本) には書いてあると思うんだけどなぁ....



my があると, その時点で「新しい変数」ができると思ってください. その有効範囲はもちろん当該場所に対する静的スコープです. また, 「変数名」もそのスコープでのみ有効です.
上の例ではサブルーチンの外で変数 $hoge を作り, その変数の名前と値をサブルーチンで共用します. だから, hoge1, hoge2 のどちらかで行った変更はもう一方でも (そして同じスコープにあるほかのどの部分からも) 見ることができます.
一方, 下の例では 2つのサブルーチンがそれぞれ個別に変数 $hoge を作ります. したがって hoge1 で宣言した $hoge は hoge2 では使えませんし, 逆に hoge2 で宣言した $hoge を hoge1 で使うこともできません (もちろん hoge1, hoge2 以外ではどちらも使えない).
さらにいうと, あるスコープ my で変数を宣言した場合, その外で同名の変数を宣言していたとしてもそれを使うことは (パッケージで修飾したりしない限り) 使えません. 下の例で, hoge1 の前に
my $hoge='foo';
とでも入れて, いろんなところで print してみるとその効果が分かると思います.
ちなみにですが, 「my で宣言すると変数の有効範囲がスコープに制限される」ことと「サブルーチン名はスコープに制限されない」ことを組み合わせると, 「複数のサブルーチンで共用したいけど外からは使ってほしくない」変数を作ることもできます. つまり,
{
my $hoge = undef;
sub hoge1 { $hoge = 1; }
sub hoge2 { $hoge = 5; }
}
とすると, この $hoge はサブルーチン hoge1, hoge2 以外では使えなくなります.

ただ, ポリシーを否定する気はないのですが老婆心ながら言わせてもらうと, 「同じ変数名をサブルーチン内で毎回宣言するのが嫌なので、サブルーチンの外でmyを宣言する」というのはあまりよいプログラミングスタイルではないですよ.
    • good
    • 0
この回答へのお礼

詳しい説明ありがとうございます。

ポリシーを否定する気ないと言いつつも否定してますね(汗)
ただ、どんなプログラミングがいいのかは独学なのでわからないもので、それが正しい書き方なのであれば各スコープで宣言するような形に変えていきたいと思います。

$hoge='foo'のくだりなどは概ね理解はしております。
ありがとうございます。

お礼日時:2010/11/13 14:01

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!