目次
この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
制御構文ではスコープを作らない(if, while、forなど)
Rubyではifやwhile、forなどの制御構文ではスコープを作りません。
if true
hoge = 'abcd'
end
p hoge #=> abcd
for i in 0..5 do
i += 1
end
p i #=> 6
# if, for内で定義された変数は抜けた後も有効
ブロックはスコープを作る(each, map, timesなど)
each, map, timesなどブロックを引数にとるメソッドでは
ブロック内でスコープが作られます。
[0,1,2].each do |i|
total ||= 0
total += i
end
p total
NameError: undefined local variable or method `total' for main:Object
from (irb):2
from /home/hoge/.rbenv/versions/2.1.8/bin/irb:11:in `<main>'
ブロック内で定義された変数totalには
外部からアクセスできません。
ブロック外で定義した変数はブロック内でも有効です。
total=10
[0,1,2].each do |i|
total ||= 0
total += i
end
p total #=> 13
制御構文もdo~endがあってブロックのように見えますが、
ブロックではないそうです(要調査)
module, class, defもスコープを作る
module, class, defもスコープを作りますが、少し違います。
この場合は外部<=>内部のアクセスはどちらもできません。
num=10
def fuga
num ||= 99
end
p num #=> 10
p fuga #=> 99
フラットスコープ
同じクラス/メソッド定義でも、class,defを使うとスコープが作られて、
Class.newやdefine_methodを使うと作られない、などもあります。
▼classで定義した場合は外側で定義したxにアクセスできない
x = 'XX'
class Hoge
def method_x
x
end
end
Hoge.new.method_x
NameError: undefined local variable or method `x' for #<Hoge:0x007fe556dbc200>
from (irb):4:in `method_x'
from (irb):7
from /home/hoge/.rbenv/versions/2.1.8/bin/irb:11:in `<main>'
▼Class.newやdefine_methodを使うと外側の変数にアクセスできる
x = 'XX'
y = 'YY'
Hoge = Class.new() do
p y #=> 'YY'
define_method(:method_x) do
x
end
end
Hoge.new.method_x #=> 'XX'
これをフラットスコープといいます。
「メタプログラミングRuby」に詳しく記載があるので
とてもおすすめです。
スコープについての記載がとても興味深かったので、
もう少し読み解いて理解を深めたいと思います。