Robert W. Hasker, 2011-2015. Blocked Previous uses of blocks words.each { |w| puts “word:...
-
Upload
shanon-baker -
Category
Documents
-
view
212 -
download
0
Transcript of Robert W. Hasker, 2011-2015. Blocked Previous uses of blocks words.each { |w| puts “word:...
BLOCKED RUBYRobert W. Hasker, 2011-2015
Blocked
Previous uses of blocks words.each { |w| puts “word: #{w}” } words.find { |x| x.size > 2 } Voter.where { |v| v.name.empty? }
Note type of Voter.all: ActiveRecord::Relation .where, etc: return WhereChain – delayed result
Other uses: infinite computations Infinite range: nats = 0..(1.0/0) Some evens:
nats.step(2).lazy.drop(50).take(10)
Uses of infinity
squares = nats.lazy.map { |n| n * n } Prime numbers:
require ‘prime’ Prime.first(10) Prime.lazy.drop(1000).
select { |x| (x+1)%2 == 0 }.first 5
How does this work? Ruby code to delay evaluation:
class Promise def initialize(&block) @block = block @delayed = true end def force @value = @block.call if @delayed @delayed = false @value end def method_missing(*args, &block) @value.__send__(*args, &block) endend
How does this work?
In general: Delay: promise to provide value when
requested Force: call in the promise
Processing list: force head when required, delay rest
Ruby implementation: blocks Useful tool when want to delay execution
in general
Yet more blockhead actions Computing Fibonacci numbers:fibonacci =
Hash.new{ |h,k|
h[k] = k < 2 ? k : h[k-1] + h[k-2] }
From Ruby documentation: If a block is specified, it will be called
with the hash object and the key, and should return the default value. It is the block’s responsibility to store the value in the hash if required.
Using blocks creatively
From Eloquent Ruby by Russ Olsen, 2011 How to log events smoothly? Consider:
class WonderApplication
def do_something doc = Document.load ‘masterwork.txt’
…
doc.save end
end
Adding loggingclass WonderApplication def initialize(logger) @logger = logger end
def do_something @logger.post ‘Starting load’ doc = Document.load ‘masterwork.txt’ @logger.post ‘Completed load’
… @logger.post ‘Starting save’ doc.save @logger.post ‘Completed save’ endend
And rescues…def do_something begin @logger.post ‘Starting load’ doc = Document.load ‘masterwork.txt’ @logger.post ‘Completed load’ rescue
@logger.post ‘Load failed’; raise end … begin @logger.post ‘Starting save’ doc.save @logger.post ‘Completed save’ rescue @logger.post ‘Save failed’; raise endend
Fix:def with_logging(description) begin @logger.post “Starting #{description}” yield @logger.post “Completed #{description}” rescue
@logger.post “#{description} failed”; raise endend
def do_somethingwith_logging(‘load’) { @doc = Document.load ‘masterwork.txt’ } … with_logging(‘save’) { @doc.save }
end
Fix:def with_logging(description) begin @logger.post “Starting #{description}” yield @logger.post “Completed #{description}” rescue
@logger.post “#{description} failed”; raise endend
def do_somethingwith_logging(‘load’) { @doc = Document.load ‘masterwork.txt’ } … with_logging(‘save’) { @doc.save }
end
“Execute around”
Blocks and initialization
Basic concept behind lazy lists: delayed initialization Consider:
class ArchivalDocument attr_reader :title, :author
def initialize(title, author, path) @title = title @author = author @path = path end def content @content = @content || File.read(path) end
end
Blocks and initialization
Basic concept behind lazy lists: delayed initialization Consider:
class ArchivalDocument attr_reader :title, :author
def initialize(title, author, path) @title = title @author = author @path = path end def content @content = @content || File.read(path) end
end
Assumption: don’t usually need content for archived object
Blocks and initialization
Basic concept behind lazy lists: delayed initialization Consider:
class ArchivalDocument attr_reader :title, :author
def initialize(title, author, path) @title = title @author = author @path = path end def content @content = @content || File.read(path) end
end
Assumption: don’t usually need content for archived object
Limitation: only works for files
Blocks to the rescue:
class ArchivalDocument attr_reader :title, :author
def initialize(title, author, &reader_block) @title = title @author = author @reader = reader_block end def content if @reader @content = @reader.call @reader = nil end @content end
end
Usage
simple_file_doc =ArchivalDocument.new(‘Rubies Forever’, ‘Tim’) doFile.read(‘c:/books/rubies_forever.txt’)
end
google_doc = ArchivalDocument.new(‘Sherlock Holmes’, ‘Conan Doyle’) do
Net::HTTP.get_response(‘books.google.com’, ‘/books?id=QhPgEq5ZeY8C’).body
end
boring_doc = ArchivalDocument.new(‘silly’, ‘Rob’) do ‘Ya’ * 100end
Summary
Infinite ranges, lists Generating streams
Execute around Embed computations in a context
Lazy initialization Application of lazy list concept to
initialization Basic principles:
Delayed execution Stored behaviors