私は次のRubyコードを持っています:
local_var = "Hello"
def hello
puts local_var
end
hello
次のエラーが表示されます。
local_variables.rb:4:in 'hello': undefined local variable or method 'local_var'
for main:Object (NameError) from local_variables.rb:7:in '<main>'
ローカル変数は、ブロック、関数、クロージャなどの外部からアクセスできないといつも思っていました。
しかし今、私はファイルにローカル変数を定義し、関数[〜#〜] inside [〜#〜]同じファイルからアクセスしようとしました。
私の理解の何が問題になっていますか?
In Rubyローカル変数は、それらが定義されたスコープでのみアクセス可能です。クラス、モジュール、またはメソッドを入力/脱退するたびに、Rubyでスコープが変更されます。
例えば :
v1 = 1
class MyClass # SCOPE GATE: entering class
v2 = 2
local_variables # => ["v2"]
def my_method # SCOPE GATE: entering def
v3 = 3
local_variables # => ["v3"]
end # SCOPE GATE: leaving def
local_variables # => ["v2"]
end # SCOPE GATE: leaving class
これらの出入りポイントは、スコープゲートと呼ばれます。メソッド定義を介してScope Gateから入力するため、hello
メソッド内でlocal_var
にアクセスできません。
Scope Flatteningコンセプトを使用して、変数をこれらのゲートに渡すことができます。
たとえば、メソッドの定義にdef
を使用する代わりに、Module#define_method
を使用できます。
local_var = "Hello"
define_method :hello do
puts local_var
end
同様に、Class#New
を介してクラスを定義できるため、クラス定義を渡すときにスコープが変更されません。
local_var = 'test'
MyClass = Class.new do
puts local_var #valid
end
の代わりに
class MyClass
puts local_var #invalid
end
同様に、モジュールゲートを介してローカル変数を渡す場合は、Module#New
を使用する必要があります。
Metaprogramming Ruby からの例