2. Outline
• Basics
of
blocks
• Scopes,
carry
variables
through
scopes
• Manipulate
scopes
using
instance_eval(
)
• Convert
blocks
to
callable
objects
• A
DSL
example
2011 8 25
3. Definition
• Definition of blocks
• Multi-lines
do ... end
• Single line
Curly braces {}
2011 8 25
4. Features
def a_method(a, b)
a + yield(a, b)
end
a_method(1,2){|x,y|(x+y)*3} #=>10
• Defined when calling a method
• Block is passed to method
• Method can call block using yield
• Blocks can have arguments
• Block can return values
2011 8 25
5. Using C#->Ruby
module Kernel
def using(resource)
begin
yield
ensure # Ensure the dispose to be called
resource.dispose
end
end
end
The exception of block called by ‘yield’ can be
always captured by ‘ensure’
2011 8 25
6. Closures
Bindings: Local variables, instance variables, self
def my_method
x = "Goodbye"
yield("cruel" )
end
x = "Hello"
my_method {|y| "#{x}, #{y} world" }
# => ?
2011 8 25
7. Using
def my_method
x = "Goodbye"
yield("cruel" )
end
x = "Hello"
my_method {|y| "#{x}, #{y} world" }
# => "Hello, cruel world"
Block definition -> find x variables -> take x to
method
2011 8 25
8. Block local variables
def my_method
yield
end
top_level_variable = 1
my_method do
top_level_variable += 1
local_to_block = 1
end
top_level_variable # => ?
local_to_block # => ?
2011 8 25
9. Block local variables
def my_method
yield
end
top_level_variable = 1
my_method do
top_level_variable += 1
local_to_block = 1
end
top_level_variable # => 2
local_to_block # => Error!
2011 8 25
10. Scope gates
v1 = 1
class MyClass
v2 = 2
local_variables
def my_method
v3 = 3
local_variables
end
local_variables
end
obj = MyClass.new
obj.my_method
obj.my_method
local_variables
2011 8 25
13. Example
my_var = "Success"
MyClass = Class.new do
puts "#{my_var} in the class definition!"
define_method :my_method do
puts "#{my_var} in the method!"
end
end
MyClass.new.my_method
# => Success in the class definition!
# => Success in the method!
2011 8 25
14. Instance_eval()
class MyClass
def initialize
@v = 1
end
end
obj = MyClass.new
obj.instance_eval do
self # => #<MyClass:0x3340dc @v=1>
@v # => 1
end
v=2
obj.instance_eval { @v = v }
obj.instance_eval { @v } # => 2 (passed to the block)
2011 8 25
15. Instance_eval()
class CleanRoom
def complex_calculation
# ...
end
def do_something
# ...
end
end
clean_room = CleanRoom.new
clean_room.instance_eval do
if complex_calculation > 10 do_something
end
end
2011 8 25
16. Callable objects
Call blocks by change it to object using proc or lambda,
A Proc is a block that has been turned into an object.
Proc:
inc = Proc.new {|x| x + 1 }
inc.call(2) # => 3
Lambda:
dec = lambda {|x| x - 1 }
dec.class # => Proc
dec.call(2) # => 1
2011 8 25
17. Procs VS Lambdas
• Procs created with lambda( ) -> lambdas
• Return
• return in lambda is more like method,
while return in procs return from scope
(defined in the scope)
• Arity
• lambdas failed with wrong arguments but
proc is ok
2011 8 25
18. methods
class MyClass
def initialize(value)
@x = value
end
def my_method
@x
end
end
object = MyClass.new(1)
m = object.method :my_method
m.call
a lambda is evaluated in the scope
Method is evaluated in the scope of its object
2011 8 25
19. Callable object wrap-up
Blocks: Evaluated in the scope in which they’re defined.
Procs: Objects of class Proc. Like blocks, they are
evaluated in the scope where they’re defined.
Lambdas: Also objects of class Proc but subtly different
from regular proc.
Methods: Bound to an object, they are evaluated in that
object’s scope. They can also be unbound from their
scope and rebound to the scope of another object.
2011 8 25
20. DSL
• DSL for individual event
• Shared among events
• Adding setup instruction
• Using & operator to pass setup
• Not using global variables
2011 8 25