https://leanpub.com/therubyclosuresbook
In computer programming, the term free variable refers to variables used in a function that are neither local variables nor parameters of that function.
source: https://en.wikipedia.org/wiki/Free_variables_and_bound_variables
snorlax_sighted = lambda do |coordinates|
lambda do
puts "SNORLAX!!! Chiong to #{coordinates}"
end
end
snorlax_sighted = lambda do |coordinates|
lambda do
puts "SNORLAX!!! Chiong to #{coordinates}"
end
end
snorlax_sighted = lambda do |coordinates|
lambda do
puts "SNORLAX!!! Chiong to #{coordinates}"
end
end
snorlax_sighted = lambda do |coordinates|
lambda do
puts "SNORLAX!!! Chiong to #{coordinates}"
end
end
"a) a function ... b) whose body references some variable that is defined in a parent scope"
source: The Ruby Closures Book
def snorlax
yield "Hyper Beam", "Sleep"
end
=> snorlax do |attack_1, attack_2|
=> puts "Snorlax attacks: #{attack_1}, #{attack_2}"
=> end
def snorlax
yield "Hyper Beam", "Sleep"
end
=> snorlax
irb(main):008:0> snorlax
LocalJumpError: no block given (yield)
from (irb):6:in `snorlax'
from (irb):8
irb(main):023:0> method :puts
=> #<Method: Object(Kernel)#puts>
irb(main):025:0> method :yield
NameError: undefined method `yield' for class `Object`
from (irb):25:in `method'
from (irb):25
def snorlax
if block_given?
yield "Hyper Beam", "Sleep"
end
end
=> snorlax
nil
def snorlax
yield "Hyper Beam", "Sleep"
end
irb=> snorlax do |attack_1|
irb=> puts attack_1
irb=> end
Hyper Beam
def snorlax
yield "Hyper Beam"
end
irb=> snorlax do |attack_1, attack_2|
irb=> puts attack_1
irb=> puts attack_2
irb=> end
Hyper Beam
irb=> nil
class Fixnum
def times
count = 0
while count < self
puts count
yield
count += 1
end
self
end
end
5.times { puts "Yay!" }
class Fixnum
def times
count = 0
while count < self
puts count
yield
count += 1
end
self
end
end
5.times { puts "Yay!" }
class Fixnum
def times
count = 0
while count < self
puts count
yield
count += 1
end
self
end
end
5.times { puts "Yay!" }
class Fixnum
def times
count = 0
while count < self
puts count
yield
count += 1
end
self
end
end
5.times { puts "Yay!" }
class Fixnum
def times
count = 0
while count < self
puts count
yield
count += 1
end
self
end
end
5.times { puts "Yay!" }
class Array
def each
index = 0
while index < self.length
puts "Yielding: #{self[index]}"
yield self[index]
index += 1
end
end
end
[1, 2, 3].each { |x| puts "Yay!" * x }
class Array
def each
index = 0
while index < self.length
puts "Yielding: #{self[index]}"
yield self[index]
index += 1
end
end
end
[1, 2, 3].each { |x| puts "Yay!" * x }
class Array
def each
index = 0
while index < self.length
puts "Yielding: #{self[index]}"
yield self[index]
index += 1
end
end
end
[1, 2, 3].each { |x| puts "Yay!" * x }
class Array
def each
index = 0
while index < self.length
puts "Yielding: #{self[index]}"
yield self[index]
index += 1
end
end
end
[1, 2, 3].each { |x| puts "Yay!" * x }
class Array
def each
index = 0
while index < self.length
puts "Yielding: #{self[index]}"
yield self[index]
index += 1
end
end
end
[1, 2, 3].each { |x| puts "Yay!" * x }
MyRouter.new do
get "/users"
post "/user/:id"
end
=> GET: /users
=> POST: /users/:id
class MyRouter
def initialize(&block)
instance_eval(&block)
end
def get(endpoint)
puts "GET: #{endpoint}"
end
def post(endpoint)
puts "POST: #{endpoint}"
end
end
MyRouter.new do
self.get "/users"
self.post "/user/:id"
end
=> GET: /users
=> POST: /users/:id
my_proc = proc { |x, y| x + y }
my_proc.call('Snor', 'lax')
=> "Snorlax"
my_proc = proc { |x, y| x + y }
my_proc.('Snor', 'lax')
=> "Snorlax"
class MyKlass
def call(pokemon)
"I choose you #{pokemon}"
end
end
MyKlass.new.("Snorlax")
=> "I choose you Snorlax"
my_proc = proc { |x, y| x + y }
my_proc['Snor', 'lax']
=> "Snorlax"
my_proc = proc { |x, y| x + y }
my_proc === ['Snor', 'lax']
=> "Snorlax"
case ['Snor', 'lax']
when my_proc
puts "I found a Snorlax"
else
# Do nothing
end
=> "I found a Snorlax"
words = %w{one two three}
words.each(&:upcase!)
=> ["ONE", "TWO", "THREE"]
words.each(&(:upcase!))
words = %w{one two three}
my_proc = proc { |x| x.upcase! }
words.map(&my_proc)
words.map { |x| x.upcase! }
=> ["ONE", "TWO", "THREE"]
class Pokemon
def to_proc
proc { |x| x.downcase! }
end
end
words.map(&(Pokemon.new))
=> ["one", "two", "three"]
words = %w{one two three}
my_proc = proc { |x| x.upcase! }
words.map(&my_proc)
words.map { |x| x.upcase! }
=> ["ONE", "TWO", "THREE"]
class Pokemon
def to_proc
proc { |x| x.downcase! }
end
end
words.map(&(Pokemon.new))
=> ["one", "two", "three"]
words = %w{one two three}
words.map(&:upcase)
class Symbol
def to_proc
proc do |object|
puts "Sending #{self} to #{object}"
object.public_send(self)
end
end
end
words.map(&:upcase)
words = %w{one two three}
words.map(&:upcase)
class Symbol
def to_proc
proc do |object|
puts "Sending #{self} to #{object}"
object.public_send(self)
end
end
end
words.map(&:upcase)
words = %w{one two three}
words.map(&:upcase)
class Symbol
def to_proc
proc do |object|
puts "Sending #{self} to #{object}"
object.public_send(self)
end
end
end
words.map(&:upcase)
numbers = [1, 2, 3]
numbers.inject(0) { |result, element| result + element }
class Symbol
def to_proc
proc do |obj, args|
puts "obj: #{obj}"
puts "args: #{args}"
obj.public_send(self, *args)
end
end
end
my_proc = proc { |a, b, c| a * b * c }.curry
my_proc.call(1).call(2).call(3)
=> 6
I consider this method (Proc#curry) to be trivial and should be treated like an Easter egg for functional programming kids. matz.
lambda { |x, y| x + y }.(1, 2)
=> 3
lambda { |x, y| x + y }.(1)
=> wrong number of arguments (given 1, expected 2)
proc { |x, y| x + y }.(1, 2)
=> 3
proc { |x, y| x + y }.(1)
=> TypeError: nil can't be coerced into Fixnum
def snorlax(proc_or_lambda)
puts "I see a snorlax"
proc_or_lambda.call
puts "Snorlax ran away"
end
snorlax(lambda { puts "Throw pokeball"; return })
=> I see a snorlax
=> Throw pokeball
=> Snorlax ran away
snorlax(proc { puts "Throw pokeball"; return })
=> LocalJumpError: unexpected return
def test
puts "Looking for snorlax"
snorlax(proc { puts "Throw pokeball"; return })
puts "Looking for another snorlax"
end
=> Looking for snorlax
=> I see a snorlax
=> Throw pokeball
def snorlax(proc_or_lambda)
puts "I see a snorlax"
proc_or_lambda.call
puts "Snorlax ran away"
end
snorlax(lambda { puts "Throw pokeball"; return })
=> I see a snorlax
=> Throw pokeball
=> Snorlax ran away
snorlax(proc { puts "Throw pokeball"; return })
=> LocalJumpError: unexpected return
def test
puts "Looking for snorlax"
snorlax(proc { puts "Throw pokeball"; return })
puts "Looking for another snorlax"
end
=> Looking for snorlax
=> I see a snorlax
=> Throw pokeball
def snorlax(proc_or_lambda)
puts "I see a snorlax"
proc_or_lambda.call
puts "Snorlax ran away"
end
snorlax(lambda { puts "Throw pokeball"; return })
=> I see a snorlax
=> Throw pokeball
=> Snorlax ran away
snorlax(proc { puts "Throw pokeball"; return })
=> LocalJumpError: unexpected return
def test
puts "Looking for snorlax"
snorlax(proc { puts "Throw pokeball"; return })
puts "Looking for another snorlax"
end
=> Looking for snorlax
=> I see a snorlax
=> Throw pokeball
def snorlax(proc_or_lambda)
puts "I see a snorlax"
proc_or_lambda.call
puts "Snorlax ran away"
end
snorlax(lambda { puts "Throw pokeball"; return })
=> I see a snorlax
=> Throw pokeball
=> Snorlax ran away
snorlax(proc { puts "Throw pokeball"; return })
=> LocalJumpError: unexpected return
def test
puts "Looking for snorlax"
snorlax(proc { puts "Throw pokeball"; return })
puts "Looking for another snorlax"
end
=> Looking for snorlax
=> I see a snorlax
=> Throw pokeball