Rubyさんの変数のスコープが思ってたんと違った
おはようございます、こんにちは、こんばんは。
スペースマーケットでWebエンジニアをしています、s0arです。
最近くしゃみやばいんですがこれ花粉すか?
自分外出自粛いいすか?
それはさておき、タイトルどおりの話です。
もう何年Rubyやってんすか?って感じなんですけどね。
いやー、マジか…ってなりました。
たとえばこういうコードがあるとするじゃないですか
i = 0
while i < 3
x = i * 2
i += 1
end
puts x
さて、puts x
はどうなると思います?
「そらループ内で宣言されてるから、xは参照できんしエラーになるやろなあ…」
そんなふうに考えていた時期が俺にもありました
正解はこう!
puts x #=> 4
!!!???!?!??!?!?!wwwwwwwwww
…俺はプログラミングを忘れたのか…?
また「独習ナントカ」からやり直しなのか…?
いや、落ち着こう
せっかくだから、俺はこのコードをJavaScriptで書くぜ!
let i = 0;
while (i < 3) {
let x = i * 2;
i++;
}
console.log(x); // ReferenceError: x is not defined
そらそうよ
ワイのエンジニア人生は間違ってなかったんや
ほなRubyさんはなんでこんなことになってるんや?
Rubyさんはforやwhileなどの制御構造でスコープを作らない
どういうことだってばよ
つまりですね、Rubyの場合だいたいこんな感じ~
ループの種類 | ループ外での変数の参照 | 説明 |
---|---|---|
whileループなどの制御構造 | 可能 | 制御構造は新しいスコープを作成しない |
eachメソッドなどのイテレータ | 不可能 | イテレータのブロックは新しいスコープを作成する |
↑ではループに限定した話をしていますが、その他の制御構造についても同じ。
制御構造についての詳細はリファレンスをチェケラ
https://docs.ruby-lang.org/ja/latest/doc/spec=2fcontrol.html
ってことで、コードにするとこうなる
# while
while_count = 0
while while_count < 3
while_x = while_count * 2
while_count += 1
end
puts while_x #=> 4
# each
[0, 1, 2].each do |each_count|
each_x = each_count * 2
end
puts each_x #=> NameError: undefined local variable or method `each_x'
ほえ~しらんかった…
なんでしらんかったんやろなあ…
いやまあ、ほら…大体こう書くよね…
i = 0
x = 0
while i < 3
x = i * 2
i += 1
end
puts x #=> 4
ループ外で参照したかったら、ループ外であらかじめ宣言してあげるよねっていう話
まとめ
お前がそう思うんならそうなんだろう
お前ん中ではな
って感じ
それでもループ入る前に宣言してあげるのが自然だよねと思いました。
あたまおかしなるで

スペースを簡単に貸し借りできるサービス「スペースマーケット」のエンジニアによる公式ブログです。 弊社採用技術スタックはこちら -> whatweuse.dev/company/spacemarket
Discussion