Lazy Initialization Pattern in Ruby

Pal David Gergely

Statzup Kft.

@nightw17

budapest.rb - 2015. 02. 25. 

What is it?

Lazy initialization of an object means that its creation is deferred until it is first used.

Why?

  • Easier to read
  • Faster to run
  • Uses less resources
    • ​Including network/databases

Simple Ruby example

class Car
  def passengers
    @passengers ||= []
  end

  def add_passenger(passenger)
    @passengers ||= []
    @passengers.push passenger
  end
end

c = Car.new

c.passengers.each do |passenger|
  puts passenger
end

#=> []

c.add_passenger('Joe')

c.passengers.each do |passenger|
  puts passenger
end

# ["Joe"]

A bit trickier example (ActiveRecord)

class Address
  def self.find_by_person(id)
    puts 'Address.find_by_person has been called!'
    'Sesame street 123'
  end
end

class Person
  def id
    4 # chosen by fair dice roll, guaranteed to be random
  end

  def address
    @address = Address.find_by_person(self.id) unless instance_variable_defined? :@address
    @address
  end
end

p = Person.new

puts p.address
# Address.find_by_person has been called!
# Sesame street 123
puts p.address
# Sesame street 123

A true Rubyism :)

require 'bigdecimal'

def prime?(n)
  return false if n < 2
  (2..Math.sqrt(n)).none? {|num| n % num == 0}
end

r = 1..BigDecimal::INFINITY

r.lazy.map{|n| n**2+1}.select{|m| prime?(m)}.first(100)

#=> [2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601, 2917, 3137, 4357, 5477, 7057, 8101,
8837, 12101, 13457, 14401, 15377, 15877, 16901, 17957, 21317, 22501, 24337, 25601, 28901, 30977,
32401, 33857, 41617, 42437, 44101, 50177, 52901, 55697, 57601, 62501, 65537, 67601, 69697, 72901,
78401, 80657, 90001, 93637, 98597, 106277, 115601, 122501, 147457, 148997, 156817, 160001,
164837, 176401, 184901, 190097, 193601, 197137, 215297, 217157, 220901, 224677, 240101, 246017,
287297, 295937, 309137, 324901, 331777, 341057, 352837, 401957, 404497, 414737, 417317, 427717,
454277, 462401, 470597, 476101, 484417, 490001, 495617, 509797, 512657, 547601, 562501, 577601,
583697, 608401, 614657, 665857, 682277, 739601]
  • Only in Ruby2.0+
  • Math!
  • "One-liner", yay!

Why not? a.k.a Problems

  • Multithreaded apps?
  • If you always use the object

Questions?

Pal David Gergely

Statzup Kft.

@nightw17

budapest.rb - 2015. 02. 25. 

Lazy Initialization Pattern in Ruby

By Pál Dávid Gergely (nightw)

Lazy Initialization Pattern in Ruby

A short presentation held at budapest.rb in 02/2015

  • 1,090