Introduction
Closures let you keep a little piece of code and the variables it uses together, so you can use them later even outside their original place.
def outer_function x = 10 inner_function = -> { puts x } inner_function end closure = outer_function closure.call
def make_printer(msg) -> { puts msg } end printer = make_printer("Hello!") printer.call
def counter count = 0 -> { count += 1 } end c = counter() puts c.call puts c.call
x = 5 closure = -> { puts x } x = 10 closure.call
def greeting_maker(name) greeting = "Hello, #{name}!" -> { puts greeting } end say_hello = greeting_maker("Alice") say_hello.call
lambda { |args| ... } or ->(args) { ... }.lambda { |x| x * 2 }, which is valid. closure = def(x) x * 2 end uses invalid syntax for a lambda. closure = function(x) { x * 2 } uses JavaScript-like syntax. closure = -> x x * 2 misses parentheses in the arrow syntax, which is invalid.def make_closures
closures = []
3.times do |i|
closures << lambda { i }
end
closures
end
closures = make_closures
closures.each { |c| puts c.call }i by value in this context, so each lambda remembers its own i value.i to 0, 1, 2 sequentially. Each lambda captures the current i value, so outputs are 0, 1, 2 respectively.closures = []
3.times do |i|
closures << lambda { j }
j = i
end
closures.each { |c| puts c.call }j before it is assigned any value in the block, causing an error when called.j is assigned after lambda creation, the lambda captures j as nil or undefined at call time, causing an error.i even if i changes later?
closures = []
3.times do |i|
closures << lambda { i }
end
closures.each { |c| puts c.call }i changes later, all lambdas see the last value.val = i inside the block, then create lambda using val. This captures the value at that iteration.val = i; closures << lambda { val } -> Option DPass the test and this pattern moves unknown