Download - Blocks by Lachs Cox
blocksLachs Cox11th April
block, akaclosure
anonymousfunction
lambda
first-classfunction
proc
Ruby<3s
Blocks
1. Reiterating the Wisdom ofBlocking
canonical use:iterator
(cliché?)
Do somethingwith each element
of an Array
an_array.each do |e| somethingend
index = 0
['hello', 'world!'].each do |word| puts "#{index += 1} #{word}" end
# >> 1 hello# >> 2 world!
index = 0
['hello', 'world!'].each do |word| puts "#{index += 1} #{word}" end
a block!
code container
index = 0
['hello', 'world!'].each do |word| puts "#{index += 1} #{word}" end
code
index = 0
['hello', 'world!'].each do |word| puts "#{index += 1} #{word}" end
block arguments
tangible(carry it in your pocket)
iterator = Proc.new do...end
portable(carry it in your pocket)
iterator = Proc.new do...end
index = 0
iterator = Proc.new do |word| puts "#{index += 1} #{word}" end
['hello', 'world!'].each(&iterator)
refactor
index = 0
iterator = Proc.new do |word| puts "#{index += 1} #{word}" end
['hello', 'world!'].each(&iterator)
refactor
specialsyntax
remembers(its own state)
remembers(binding to creation context)
(its own state)
index = 0
['hello', 'world!'].each do |word| puts "#{index += 1} #{word}" end
binding
['hello', 'world!'].each do |word| puts "#{index += 1} #{word}" end
local varsself
block
code
binding
arguments returnvalue
a portable code container which remembers its state
and creation context.
a block:
for word in words puts wordend
words.each do |word| puts wordend
pssst...!
for word in words puts wordend
words.each do |word| puts wordend
equivalent
identical
binding
pssst...!
binding
pssst...!
Kernel#binding
(use it for evil)
2. TMTOWTDI
stylearray.each {|word| puts word}
array.each do |word| puts word index += 1end
Basics
Syntax sugar.+
Kernel#procKernel#lambda
Proc#new
block = Proc.new do |action|
puts "#{self} #{action}s #{beer}"
end
block = lambda do |action|
puts "#{self} #{action}s #{beer}"
end
Syntax sugar.
(the real power)
def perform_action(action,block) block.call(action)end
beer = "beez neez"
block = lambda do |action| puts "#{self} #{action}s #{beer}"endperform_action(:drink,block) # >> main drinks beez neez
def perform_action(action) yield actionend
beer = "beez neez"
perform_action(:drink) do |action| puts "#{self} #{action}s #{beer}"end# >> main drinks beez neez
def perform_action(action,block) block.call(action)end
def perform_action(action,&block) yield action if block_given?end
def perform_action(action) yield action if block_given?end
def perform_action(action) yield actionend
&captures implicit
blocks
&last arg
def foo(...,&block)
&last arg
def foo(...,&block)
only one per method
def foo(&block) block.class # => Proc, Proc, Proc block.arity # => -1, 0, 1end
foo { nil }foo { || nil }foo { |a| nil }
nuancesgo here
argument pattern matching
perform_action([:drink,:eat,:be_merry]) do |(a,*b)| a # => :drink b # => [:eat, :be_merry]end
perform_action([:ignore,:regard]) do |(_,a)| a # => :regardend
3. The BuildingBlocks of a
Perfect Meal
Roll your ownEnumerable
Roll your ownEnumerable
you implement each(&block)
Roll your ownEnumerable
you implement each(&block)def each(&block) (Hpricot(open(url)) / "a") .map {|a| a['href']} .each(&block)end
Roll your ownEnumerable
you implement each(&block)def each(&block) @brewery_visitor.rewind while brewery = @brewery_visitor.next yield brewery endend
Roll your ownEnumerable
include Enumerable
Roll your ownEnumerable
include Enumerableyou get
all?, any?, collect, detect, each_cons, each_slice, each_with_index, entries, enum_cons, enum_slice, enum_with_index, find, find_all, grep, include?,
inject, map, max, member?, min, partition, reject, select, sort, sort_by, to_a, to_set, zip
Customised Behaviour& Callbacks
class BeerController < ApplicationController append_before_filter do @beer = Beer.find(params[:id]) endend
RefactoringIdeas
RefactoringIdeas
mixin module
RefactoringIdeas
extract subclassmixin module
RefactoringIdeas
extract subclassmixin module
template pattern
RefactoringIdeas
extract subclassmixin module
template pattern
logic blocks
4. Yielding Secretsof Erb
bonus 1
def __render_...(local_vars) # copy local vars
end
templaterhtml Erb
templatecodeString
evalrender
templatemethod
send(:__render..., local_assigns) do |*name| instance_variable_get "@content_for_#{name.first || 'layout'}"end
<%= yield %> # => @content_for_layout<%= yield :clean %> # => @content_for_clean<%= yield :clean, :dirty %> # => @content_for_clean
5. An EmpiricalApproach Using
Text–mate
bonus 2
http://eigenclass.org/hiki/rcodetools
xmpfilter by mfp
+
explore[:a,:b,:c].each do |c| c puts c end
explore[:a,:b,:c].each do |c| c puts c end
[:a,:b,:c].each do |c| c # => puts c # => end
#⇥
# =>
Execute and Update ‘# =>’ Markers
⌃⇧⌘E
explore[:a,:b,:c].each do |c| c puts c end
[:a,:b,:c].each do |c| c # => puts c # => end
[:a,:b,:c].each do |c| c # => :a, :b, :c puts c # => nil, nil, nil end# >> a# >> b# >> c