Thomas Leitner
@gettalong
@_gettalong
1.upto(10) {|n| puts n }
block = proc {|n| puts n}
1.upto(10, &block)
Equivalent to Proc.new
block = lambda {|n| puts n}
1.upto(10, &block)
return
works differently
p = proc {|a, b| [a, b]}
l = lambda {|a, b| [a, b]}
x = "string"
def x.to_ary; chars.to_a; end
# using p using l
.call(1) # => [1, nil] ArgumentError (given 1, expected 2)
.call(1, 2) # => [1, 2] [1, 2]
.call(1, 2, 3) # => [1, 2] ArgumentError (given 3, expected 2)
.call([1, 2]) # => [1, 2] ArgumentError (given 1, expected 2)
.call(x) # => ["s", "t"] ArgumentError (given 1, expected 2)
return
behaviorp = proc { return 1 }
l = lambda { return 1 }
p.call # => LocalJumpError: unexpected return
l.call # => 1
Proc#lambda?
to determine “lambdaness”f = Fiber.new do |initial|
middle = Fiber.yield(initial)
Fiber.yield("before middle")
ending = Fiber.yield(middle)
end
f.resume("initial") # => "initial"
f.resume("middle") # => "before middle"
f.resume("ignored") # => "middle"
f.resume("end") # => "end"
f.resume # => FiberError: dead fiber called
def fiber
nr_invoked = 0
store = nil
proc do |param|
case (nr_invoked += 1)
when 2 then store = param; "before middle"
when 3 then store
else param
end
end
end
f = fiber
f.call("initial") # => "initial"
f.call("middle") # => "before middle"
f.call("ignored") # => "middle"
f.call("end") # => "end"
f.call # => nil
require 'fiber'
f1 = Fiber.new { "fiber 1" }
f2 = Fiber.new { "fiber 2"; f1.transfer; Fiber.yield "after" }
f2.resume # => "fiber 1"
f2.resume # => FiberError: double resume
f2.transfer # => "after"
f2.resume # => FiberError: cannot resume transferred Fiber
f2.transfer # => nil
consumer(filter_a(filter_b(producer)))
def producer(io)
Fiber.new do
while (data = io.read(2**16))
Fiber.yield(data)
end
end
end
def consumer(producer)
str = ''.b
while producer.alive? && (data = producer.resume)
str << data
end
str
end
def ascii_hex_decode(source)
Fiber.new do
rest = nil
while source.alive? && (data = source.resume)
data = rest << data if rest
rest = (data.size.odd? ? data.slice!(-1, 1) : nil)
Fiber.yield([data].pack('H*'))
end
[rest].pack('H*') if rest
end
end
consumer(filter(producer))
)Fiber.yield
and Fiber#resume
can be used to exchange dataFiber#transfer
Slides available at
http://talks.gettalong.org/2017-03-viennarb/
/