Skip to content

Instantly share code, notes, and snippets.

@lnznt
Created January 10, 2015 23:41
Show Gist options
  • Save lnznt/6c3641f4a9fce40aaa4a to your computer and use it in GitHub Desktop.
Save lnznt/6c3641f4a9fce40aaa4a to your computer and use it in GitHub Desktop.
a = 10
p [1,2,3].map {|n| n * a } #=> [10, 20, 30]
a = 10 # main に変数`a`を定義する。
f1 = -> { a * 2 } # クロージャは変数`a`を包む。`a`の参照するオブジェクト「`10`」を包むのではない
a = 100 # 変数`a`の参照するオブジェクトを変更
p f1.() #=> 200 # クロージャ実行時に`a`が参照するオブジェクト「`100`」を評価
v = 10
# instance_eval は self をレシーバにしてブロックを評価する
instance_eval do # ここでは、レシーバが self なので self を self にしている。
a = 1 # ブロック内(ダイナミックスコープ)の変数
b = 2 # ブロック内(ダイナミックスコープ)の変数
p a #=> 1
p b #=> 2
p v #=> 10 # ブロック外(レキシカルスコープ)の変数
end
p v #=> 10
p a # エラー! (NameError: undefined local variable or method `a' ...)
p b # エラー! (NameError: undefined local variable or method `b' ...)
f2 = -> { b * 2 } # 変数`b`はブロック内の変数
b = 1000 # main に変数`b`を定義する。しかし、ブロック内の変数`b`とは別物。
# さらに、クロージャ定義時にはこの変数は定義されてないので、クロージャに包まれていない。
p f2.() # NameError: undefined local variable or method `b' for main:Object 。。。(;_;)
g = -> { a = 10 ; -> { a * 2 } } # g は関数 (-> { a * 2 }) を返す高階関数
f = g.()
f.() #=> 20
g = -> { count = [] ; -> { count << :x } }
f1 = g.() # f1 のコール f2 のコール
f1.() #=> [:x] # 1回目
f1.() #=> [:x, :x] # 2回目
f1.() #=> [:x, :x, :x] # 3回目
f2 = g.()
f2.() #=> [:x] # 1回目
f2.() #=> [:x, :x] # 2回目
f1.() #=> [:x, :x, :x, :x] # 4回目
b1 = f1.binging
p b1.class #=> Binding
p b1.local_variable_get(:count) #=> [:x, :x, :x, :x]
b1.local_variable_set(:count, []) # カウンタをリセットしてみる
p f1.() #=> [:x]
p f1.() #=> [:x, :x]
class Binding
alias [] local_variable_get
alias []= local_variable_set
end
g = -> { a = 0 ; -> { a += 1 } }
f = g.()
f.() #=> 1
f.() #=> 2
f.() #=> 3
b = f.binding
p b[:a] #=> 3
b[:a] = 10 # 変数`a` の値を 10 にする
f.() #=> 11
f.() #=> 12
g = -> { a = 10; -> { x = 2; a * 2 } }
f = g.()
b = f.binding
b.local_variable_get :a #=> 10
b.local_variable_get :x # エラー (NameError: local variable `x' not defined for #<Binding:...)
obj = Object.new
b = obj.send(:binding) # private メソッドだが、send でなら呼び出せる
p b.class #=> Binding
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment