プログラミングを学び始めた頃は当然分からないことだらけで多分本を読んでも理解できない事の方が圧倒的に多い。
"式が値を返す"というのも最初は何の事だかいまいちピンとこなかった。
"関数が値を返す"というのは何となく分かりやすい、関数定義の中で

sub {
    my $name = shift;
    return $name;
}

とすれば名前が返ってくるんだなと。

例えばPerlで

my @colors = qw/White Blue Red Green Yellow/;

while (my $color = shift(@colors)) {
    print $color."\n";
}

こんなコードがあったとして、
"while"の条件判断が成立するのは"my $color = shift(@colors)"という代入文(代入式)が値を返しているからだ。
shift(@colors)は配列の最初の要素を削除しながらその要素を返すのでいずれ配列は空になる。
配列が空になれば条件分岐がfalseになりループは終了する。

Rubyでも同じように動作する

colors = %w/White Blue Red Green Yellow/

while color = colors.shift do
    puts color
end

同様にPHPでも動く。
PerlでもRubyでも配列のループでWhileはあまり使わないと思うが、これが出来るんなら当然Pythonも、と思ってしまう。

ところがうまく行かない。

colors = ["White", "Blue", "Red", "Green", "Yellow"]

while color = colors.pop(0):
    print color

Pythonで上のコードを書いて実行するとエラーになってしまう。

なぜエラーになるかというとPythonの代入文は値を返さないからだ。
実際は値を返さない訳ではなくNoneという値を返しているらしいが、それでも"while"の条件がfalseになるとかじゃなくて"SyntaxError"になってしまう。
ここで"式が値を返す"とはどういう事かがよく理解できた。
Pythonの場合こう書けばうまくいく

while colors:
    print colors.pop(0)

ちなみに上記のようなコードをPerlで書いてみる。

my @colors = qw/White Blue Red Green Yellow/;
while (@colors) {
    print shift(@colors)."\n";
}

これはうまくいく。
ところがRubyで

colors = %w/White Blue Red Green Yellow/

while colors do
    puts colors.shift
end

こう書いてもうまくはいかない。
構文が間違っててエラーが出るとかじゃなくて無限ループに入ってしまうのだ。

これはRubyの配列はたとえ空っぽでも条件判断した時はtrueになるからだ。
たしかRubyで条件がfalseになるのはfalseとnilだけだったような・・。数字の0もtrueになる。

似ていると思っている言語でも微妙な違いがある。
Rubyの場合はこれでうまく行く。

colors = %w/White Blue Red Green Yellow/

while !colors.empty? do
    puts colors.shift
end

empty?は中身が空かどうかをチェックしてくれるメソッド。

カテゴリ:

トラックバック(0)

トラックバックURL: http://blog.beanz-net.jp/beanz_mtos/mt-tb.cgi/4

コメントする