Download presentation
Presentation is loading. Please wait.
Published byEarl Daniels Modified over 8 years ago
1
Robert W. Hasker, 2011-2016
2
Previous uses of blocks words.each { |w| puts “word: #{w}” } words.find { |x| x.size > 2 } words.select { |x| x.size % 2 == 0 } Another use: infinite computations Open irb and type nats = 0..(1.0/0) nats.take(100) nats.step(2).first(10) Skipping: nats.step(2).lazy.drop(50).first(10) Blocked
3
Previous uses of blocks words.each { |w| puts “word: #{w}” } words.find { |x| x.size > 2 } words.select { |x| x.size % 2 == 0 } Another use: infinite computations Open irb and type nats = 0..(1.0/0) nats.take(100) nats.step(2).first(10) Skipping: nats.step(2).lazy.drop(50).first(10) Blocked Lazy list
4
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)%3 == 0 }.first(5)
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
6
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
7
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.
8
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
9
Adding logging class 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’ end
10
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 end
11
Fix: def with_logging(description) begin @logger.post “Starting #{description}” yield @logger.post “Completed #{description}” rescue @logger.post “#{description} failed”; raise end def do_something with_logging(‘load’) { @doc = Document.load ‘masterwork.txt’ } … with_logging(‘save’) { @doc.save } end
12
Fix: def with_logging(description) begin @logger.post “Starting #{description}” yield @logger.post “Completed #{description}” rescue @logger.post “#{description} failed”; raise end def do_something with_logging(‘load’) { @doc = Document.load ‘masterwork.txt’ } … with_logging(‘save’) { @doc.save } end “Execute around”
13
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
14
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
15
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
16
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
17
Usage simple_file_doc = ArchivalDocument.new(‘Rubies Forever’, ‘Tim’) do File.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’ * 100 end
18
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
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.