Ruby BLocks and more
Abhishek Yadav
Jan 2019
Agenda
- Lambdas, closures, and blocks
- Iterators, Enumerable
- map, reduce
- Lazy
- Function like
- Closure
- Anonymous
Lambda
l1 = lambda { |x| "hello world " + x }
l2 = ->(x) { "hello world " + x }
l3 = lambda do |x|
"hello world " +x
end
# invoke:-
l1.call("Abhi")
l2.("Abhi")
l3["Abhi"]
m='Mr'
l4 = ->(x) { "hello #{m} #{x}" }
# invoke:-
l4.("Rick") # => "hello Mr Rick"
m='Miss'
l4.("Rachel") # => "hello Miss Rachel"
- Function like
- Closure
- Anonymous
Lambda
def salutation(name)
%w(Mr Miss).sample
end
def with_respect(name)
s = salutation(name)
yield (s + name)
end
# invoke:-
with_respect('Rick') { |x| "Hello #{x}" }
- Function like √
- Closure √
- Anonymous √
- Can be invoked only once
- Not an object
Blocks
This part
def foo
yield
end
foo { "hello world" }
# ^^ is somewhat similar to -
def bar(l)
l.call
end
bar ->{ "Hello world" }
- Function like √
- Closure √
-
Anonymous √
- Can be invoked with yield
Blocks
# Invoke with argument
def foo
mood = ['🙂', '😠'].sample
yield mood # call the block with the mood
end
foo { |mood| "hello world #{mood}" }
# Not an object.
x = { |mood| "hello world #{mood}" } # => error
- Function like √
- Closure √
-
Anonymous √
- Can be invoked with yield
- Not an object - Cant be assigned to a variable
Blocks
# Invoke with argument
def foo
mood = ['🙂', '😠'].sample
yield mood # call the block with the mood
end
def outer_foo
foo do |mood|
return if mood == '😠'
"hello world #{mood}"
end
puts "ok!"
end
- Function like √
- Closure √
-
Anonymous √
- Can be invoked with yield
- Not an object - Cant be assigned to a variable
- Has non local return
Blocks
# Invoke with argument
def foo
mood = ['🙂', '😠'].sample
yield mood # call the block with the mood
end
def outer_foo
foo { |mood|
return if mood == '😠'
"hello world #{mood}"
}
puts "ok!"
end
- Function like √
- Closure √
-
Anonymous √
- Can be invoked with yield
- Not an object - Cant be assigned to a variable
- Has non local return
Blocks
# Invoke with argument
x = 123
def foo
puts x # <- error
end
# method_missing
# define_method
- Function like √
- Closure x
-
Anonymous x
- Used for OOP
- Can access instance variables
- Are attached dynamically
- Can be defined dynamically (metaprogramming)
Methods
# Invoke with argument
x = 123
def foo
puts x # <- error
end
# method_missing
# define_method
- Function like √
- Closure x
-
Anonymous x
- Used for OOP
- Can access instance variables
- Are attached dynamically
- Can be defined dynamically (metaprogramming)
Methods
class Foo
def step1
puts 'start'
1 + 1
puts 'end'
end
def step2
puts 'start'
2 + 2
puts 'end'
end
def step3
puts 'start'
3 + 3
puts 'end'
end
end
- Use blocks when there is common 'surround' code
Log example
class Foo1
def step1
with_log { 1 + 1 }
end
def step2
with_log { 2 + 2 }
end
def step3
with_log { 3 + 3 }
end
def with_log
puts 'start'
yield
puts 'end'
end
end
- Use blocks when there is common 'surround' code
Log example
class Foo2
def step1
with_log(:step1) { 1 + 1 }
end
def step2
with_log(:step2) { 2 + 2 }
end
def step3
with_log(:step3) { 3 + 3 }
end
def with_log(step)
puts "start #{step}"
yield
puts "end #{step}"
end
end
- Use blocks when there is common 'surround' code
Log example
# This pattern gets repeated,
# with some variations to our logic
data['OrderedItems'].each do |ordered_item|
ordered_item['TestContent'].each do |test_content|
# Our logic here
end
end
- When we need to iterate over something cumbersome
Custom iterators
# This pattern gets repeated,
# with some variations to our logic
def my_each(data)
data['OrderedItems'].each do |ordered_item|
ordered_item['TestContent'].each do |test_content|
yield(test_content)
end
end
end
values = []
my_each(results) do |test_data|
values << test_data['Value']
end
- When we need to iterate over something cumbersome
Custom iterators
class MyArr
def initialize
@arr = []
end
def push(val)
@arr << val
end
def myeach
@arr.each do |val|
yield val
end
end
end
- When we need to iterate over something cumbersome
- Use Enumerator where possible
Custom iterators
def my_each1(data)
arr = MyArr.new
data['OrderedItems'].each do |ordered_item|
ordered_item['TestContent'].each do |test|
if block_given?
yield(test)
else
arr.push(test)
end
end
end
arr.to_enum(:myeach)
end
> my_each1(data).map { |x| x['Value'] }
- Map and reduce
- Lazy
More...
Ruby BLocks and more
By Abhishek Yadav
Ruby BLocks and more
- 927