Blocks by Lachs Cox

71
blocks Lachs Cox 11th April

description

A beginner's guide to Ruby blocks. It might be a bit hard to follow w/o the talk to go along with it. From April 2007

Transcript of Blocks by Lachs Cox

Page 1: Blocks by Lachs Cox

blocksLachs Cox11th April

Page 2: Blocks by Lachs Cox

block, akaclosure

anonymousfunction

lambda

first-classfunction

proc

Page 3: Blocks by Lachs Cox

Ruby<3s

Blocks

Page 4: Blocks by Lachs Cox

1. Reiterating the Wisdom ofBlocking

Page 5: Blocks by Lachs Cox

canonical use:iterator

(cliché?)

Page 6: Blocks by Lachs Cox

Do somethingwith each element

of an Array

Page 7: Blocks by Lachs Cox

an_array.each do |e| somethingend

Page 8: Blocks by Lachs Cox

index = 0

['hello', 'world!'].each do |word| puts "#{index += 1} #{word}" end

Page 9: Blocks by Lachs Cox

# >> 1 hello# >> 2 world!

Page 10: Blocks by Lachs Cox

index = 0

['hello', 'world!'].each do |word| puts "#{index += 1} #{word}" end

a block!

Page 11: Blocks by Lachs Cox

code container

Page 12: Blocks by Lachs Cox

index = 0

['hello', 'world!'].each do |word| puts "#{index += 1} #{word}" end

code

Page 13: Blocks by Lachs Cox

index = 0

['hello', 'world!'].each do |word| puts "#{index += 1} #{word}" end

block arguments

Page 14: Blocks by Lachs Cox

tangible(carry it in your pocket)

iterator = Proc.new do...end

Page 15: Blocks by Lachs Cox

portable(carry it in your pocket)

iterator = Proc.new do...end

Page 16: Blocks by Lachs Cox

index = 0

iterator = Proc.new do |word| puts "#{index += 1} #{word}" end

['hello', 'world!'].each(&iterator)

refactor

Page 17: Blocks by Lachs Cox

index = 0

iterator = Proc.new do |word| puts "#{index += 1} #{word}" end

['hello', 'world!'].each(&iterator)

refactor

specialsyntax

Page 18: Blocks by Lachs Cox

remembers(its own state)

Page 19: Blocks by Lachs Cox

remembers(binding to creation context)

(its own state)

Page 20: Blocks by Lachs Cox

index = 0

['hello', 'world!'].each do |word| puts "#{index += 1} #{word}" end

binding

Page 21: Blocks by Lachs Cox

['hello', 'world!'].each do |word| puts "#{index += 1} #{word}" end

local varsself

Page 22: Blocks by Lachs Cox

block

code

binding

arguments returnvalue

Page 23: Blocks by Lachs Cox
Page 24: Blocks by Lachs Cox
Page 25: Blocks by Lachs Cox

a portable code container which remembers its state

and creation context.

a block:

Page 26: Blocks by Lachs Cox

for word in words puts wordend

words.each do |word| puts wordend

pssst...!

Page 27: Blocks by Lachs Cox

for word in words puts wordend

words.each do |word| puts wordend

equivalent

identical

Page 28: Blocks by Lachs Cox

binding

pssst...!

Page 29: Blocks by Lachs Cox

binding

pssst...!

Kernel#binding

(use it for evil)

Page 30: Blocks by Lachs Cox

2. TMTOWTDI

Page 31: Blocks by Lachs Cox

stylearray.each {|word| puts word}

array.each do |word| puts word index += 1end

Page 32: Blocks by Lachs Cox

Basics

Syntax sugar.+

Page 33: Blocks by Lachs Cox

Kernel#procKernel#lambda

Proc#new

Page 34: Blocks by Lachs Cox

block = Proc.new do |action|

puts "#{self} #{action}s #{beer}"

end

Page 35: Blocks by Lachs Cox

block = lambda do |action|

puts "#{self} #{action}s #{beer}"

end

Page 36: Blocks by Lachs Cox

Syntax sugar.

(the real power)

Page 37: Blocks by Lachs Cox

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

Page 38: Blocks by Lachs Cox

def perform_action(action) yield actionend

beer = "beez neez"

perform_action(:drink) do |action| puts "#{self} #{action}s #{beer}"end# >> main drinks beez neez

Page 39: Blocks by Lachs Cox

def perform_action(action,block) block.call(action)end

Page 40: Blocks by Lachs Cox

def perform_action(action,&block) yield action if block_given?end

Page 41: Blocks by Lachs Cox

def perform_action(action) yield action if block_given?end

Page 42: Blocks by Lachs Cox

def perform_action(action) yield actionend

Page 43: Blocks by Lachs Cox

&captures implicit

blocks

Page 44: Blocks by Lachs Cox

&last arg

def foo(...,&block)

Page 45: Blocks by Lachs Cox

&last arg

def foo(...,&block)

only one per method

Page 46: Blocks by Lachs Cox

def foo(&block) block.class # => Proc, Proc, Proc block.arity # => -1, 0, 1end

foo { nil }foo { || nil }foo { |a| nil }

Page 47: Blocks by Lachs Cox

nuancesgo here

Page 48: Blocks by Lachs Cox

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

Page 49: Blocks by Lachs Cox

3. The BuildingBlocks of a

Perfect Meal

Page 50: Blocks by Lachs Cox

Roll your ownEnumerable

Page 51: Blocks by Lachs Cox

Roll your ownEnumerable

you implement each(&block)

Page 52: Blocks by Lachs Cox

Roll your ownEnumerable

you implement each(&block)def each(&block) (Hpricot(open(url)) / "a") .map {|a| a['href']} .each(&block)end

Page 53: Blocks by Lachs Cox

Roll your ownEnumerable

you implement each(&block)def each(&block) @brewery_visitor.rewind while brewery = @brewery_visitor.next yield brewery endend

Page 54: Blocks by Lachs Cox

Roll your ownEnumerable

include Enumerable

Page 55: Blocks by Lachs Cox

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

Page 56: Blocks by Lachs Cox

Customised Behaviour& Callbacks

class BeerController < ApplicationController append_before_filter do @beer = Beer.find(params[:id]) endend

Page 57: Blocks by Lachs Cox

RefactoringIdeas

Page 58: Blocks by Lachs Cox

RefactoringIdeas

mixin module

Page 59: Blocks by Lachs Cox

RefactoringIdeas

extract subclassmixin module

Page 60: Blocks by Lachs Cox

RefactoringIdeas

extract subclassmixin module

template pattern

Page 61: Blocks by Lachs Cox

RefactoringIdeas

extract subclassmixin module

template pattern

logic blocks

Page 62: Blocks by Lachs Cox

4. Yielding Secretsof Erb

bonus 1

Page 63: Blocks by Lachs Cox

def __render_...(local_vars) # copy local vars

end

templaterhtml Erb

templatecodeString

evalrender

templatemethod

Page 64: Blocks by Lachs Cox

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

Page 65: Blocks by Lachs Cox

5. An EmpiricalApproach Using

Text–mate

bonus 2

Page 66: Blocks by Lachs Cox

http://eigenclass.org/hiki/rcodetools

xmpfilter by mfp

+

Page 67: Blocks by Lachs Cox

explore[:a,:b,:c].each do |c| c puts c end

Page 68: Blocks by Lachs Cox

explore[:a,:b,:c].each do |c| c puts c end

[:a,:b,:c].each do |c| c # => puts c # => end

Page 69: Blocks by Lachs Cox

#⇥

# =>

Page 70: Blocks by Lachs Cox

Execute and Update ‘# =>’ Markers

⌃⇧⌘E

Page 71: Blocks by Lachs Cox

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