Ruby : Block, Proc and, lambda

Post on 28-Nov-2014

4,772 views 3 download

description

En tant que formateur Ruby, je rencontre régulièrement des développeurs manipulant les block, Proc et lambda sans toujours comprendre comment cela fonctionne. J'ai donc eu l'idée de faire cette présentation au Meetup Paris.rb. (10 décembre 2012)

transcript

Block, Proc and, lambda

2

Formateur Ruby on Rails @human_coders

Matthieu Segret

1

Block

3

Block

names.each do |name| puts name end

names.each { |name| puts name }

names = ["Matz","DHH","Aaron"]

4

yield

def call_this_block_twice yield yieldend

MatzMatzcall_this_block_twice { puts "Matz" }

5

def call_this_block yield("Matz")end

Matz

yield - Arguments

call_this_block {|name| puts name}

6

yield - Return value

def puts_this_block block_result = yield puts block_resultend

puts_this_block {"Matz"} Matz

7

def call_this_block yield("Matz")end

no block given

yield - Optional block

call_this_block

8

def call_this_block yield("Matz") if block_given?end

yield - Optional block

call_this_block

9

yield - Scope 1

def call_this_block yieldend

x = 5puts "value of x before: #{x}"call_this_block { x += 1 }puts "value of x after: #{x}" value of x after: 6

value of x before: 5

10

yield - Scope 2

def call_this_block x = 100 yield puts "value of x at end of call_this_block_x: #{x}"end

x = 5call_this_block { x += 1 }

puts "value of x after: #{x}" value of x after: 6

value of x at end of call_this_block_x: 100

11

{|name| puts name}

What if we wanted to store this block, for execution later?

12

Proc & lambda

13

Proc & lambda

my_proc = Proc.new {|x| puts x}my_proc.call("Matz")

Proc

Matz

my_lambda = lambda {|x| puts x}my_lambda.call("DHH")

Lambda

DHH

my_lambda = ->(x) {puts x}my_lambda.call("Aaron")

Lambda Ruby 1.9

Aaron

14

def bar f = lambda { return "return from inside lambda" } f.call return "return from bar" endputs bar

Lambda

def foo f = Proc.new { return "return from inside proc" } f.call return "return from foo" endputs foo

Proc

Proc vs lambda : return

return from bar

return from inside proc

15

Proc vs lambda : arity

my_proc = Proc.new {|x,y| puts "(#{x},#{y})"}my_proc.call(1,2,3)my_proc.call(1)

Proc

(1,2)(1,)

my_lambda = lambda {|x,y| puts "(#{x},#{y})"}my_lambda.call(1,2,3)my_lambda.call(1)

Lambda

wrong number of arguments ...

16

Multiple lambda

def post(success, error) ... if ... success.call else error.call end end

post(-> {puts "Sent!"}, -> {raise 'Auth Error'})

17

Lambda to block

names = ["Matz","DHH","Aaron"]names.each do |name| puts nameend

names = ["Matz","DHH","Aaron"]printer = lambda {|name| puts name}names.each( printer)& lambda to block

18

Proc to block

names = ["Matz","DHH","Aaron"]names.each do |name| puts nameend

names = ["Matz","DHH","Aaron"]printer = Proc.new {|name| puts name}names.each( printer)& Proc to block

19

Block to Proc

def call_this_block yield("Matz")end

def call_this_block(&block) block.call("Matz")end

block to Proc

20

Symbol#to_proc

tweets.map { |tweet| tweet.user }

tweets.map(&:user) Symbol to Proc

21

Method#to_proc

def method_user(tweet) tweet.userend

tweets.map(&method(:method_user)) Method to Proc

method(:method_user)

22

23

Thanks@matthieusegret

24