LAZY, LAZY, LAZY, ALL
THE THINGS!
WHAT IS LAZY
PROGRAMMING?
IT DOES NOT MEAN
LETTING AN IDE WRITE
CODE FOR US
IT DOES NOT MEAN
ASKING SIRI TO DO
DATABASE MIGRATIONS
IT IS NOT WRITING CODE
ON A GLOOMY MONDAY
WITH A CUP OF COFFEE
WHAT IS IT THEN ?
IT CAN BE A
SIMPLE EXPRESSION
OR,
A DESIGN PATTERN
PERHAPS, EVEN A
LANGUAGE SEMANTIC
WHY AM I TELLING YOU
THIS ?
Lazy, Lazy, Lazy all the things !
LAZINESS IS THE QUALITY THAT
MAKES YOU GO TO GREAT EFFORT TO
REDUCE OVERALL ENERGY
EXPENDITURE.
Larry Wall
BECAUSE,
YOU HAVE TO BE LAZY TO BE A
RUBY PROGRAMMER
Yukihiro ‘Matz’ Matsumoto
AND,
LET’S BE LAZY
1. LAZY EVALUATION
2. LAZY LOADING
3. LAZY INHERITANCE
LAZY EVALUATION
THE EXPRESSION
DELAYING EVALUATION
OF AN EXPRESSION
UNTIL IT'S REQUIRED
GIVING US THE ABILITY
TO ABSTRACT THE
CONTROL FLOW
EXAMPLE
ABSTRACTING THE CONTROL FLOW PART 1 - THE PLEDGE
INITIALISE AN OBJECT
▸All we need to do is initialise an
object
▸But we need to check if its nil or not
▸Seriously, how hard can that be?
ABSTRACTING THE CONTROL FLOW PART 1 - THE TURN
INITIALISE AN OBJECT
if @foo.nil?
@foo = :bar
end
ABSTRACTING THE CONTROL FLOW PART 1 - THE PRESTIGE
INITIALISE AN OBJECT, LAZILY
@foo ||= :bar
THAT WAS SIMPLE
ENOUGH
NOW, A MORE USEFUL
EXAMPLE
ABSTRACTING THE CONTROL FLOW PART 2 - THE PLEDGE
FETCHING AN AUTHENTICATION TOKEN
▸Communicate with an API
▸Fetch an Authentication Token
▸Use it
ABSTRACTING THE CONTROL FLOW PART 2 - THE TURN
SEND A REQUEST, AND SAVE THE TOKEN
require 'restclient'
class Authenticator
attr_reader :auth_token
def auth_token url
res = RestClient.get(url)
@auth_token = parse_response_for_token(res)
end
def parse_response_for_token response
# parsing logic here, returns a hash
end
end
ABSTRACTING THE CONTROL FLOW PART 2 - THE PRESTIGE
SEND A REQUEST, AND SAVE THE TOKEN, LAZILY
require 'restclient'
class Authenticator
attr_reader :auth_token
def auth_token url
@auth_token ||= (res = RestClient.get(url) &&
parse_response_for_token(res))
end
def parse_response response
# parsing logic here, returns a hash
end
end
THIS LOOKS
SUSPICIOUSLY LIKE
CACHING
CACHING = LAZINESS
MIND = BLOWN!
Lazy, Lazy, Lazy all the things !
Lazy, Lazy, Lazy all the things !
ANOTHER EXAMPLE
LONG SEQUENCES PART 1 - THE PLEDGE
CALCULATE SUM OF FIRST THOUSAND EVEN NUMBERS
▸Iterate 2000 times
▸Check if the number is even
▸Add to a sum if it is.
LONG SEQUENCES PART 1 - THE TURN
LOOP IT, SUM IT, RETURN IT
def sum_of_thousand_even_numbers
sum = 0
2001.times do |number|
sum += number if number % 2 == 0
end
sum
end
sum_of_even_numbers(1000)
=> 1001000
THAT’S NOT THE RUBY
WAY, IS IT ?
LONG SEQUENCES PART 1 - THE TURN
RANGE IT, SELECT IT, REDUCE IT
def sum_of_even_numbers limit
(1..limit*2)
.select(&:even?)
.reduce(:+)
end
sum_of_even_numbers(1000)
=> 1001000
LONG SEQUENCES PART 1 - THE TURN
RANGE IT, SELECT IT, TAKE IT, REDUCE IT
def sum_of_even_numbers limit
(1..Float::INFINITY)
.select(&:even?)
.take(limit)
.reduce(:+)
end
LONG SEQUENCES PART 1 - THE TURN
RANGE IT, SELECT IT, TAKE IT, REDUCE IT
def sum_of_even_numbers limit
(1..Float::INFINITY)
.select(&:even?)
.take(limit)
.reduce(:+)
end
DANG! INFINITE LOOP !
LONG SEQUENCES PART 1 - THE PRESTIGE
RANGE IT, SELECT IT, TAKE IT, REDUCE IT, LAZILY
def sum_of_even_numbers limit
(1..Float::INFINITY)
.lazy
.select(&:even?)
.take(limit)
.reduce(:+)
end
sum_of_even_numbers(1000)
=> 1001000
THAT WAS PEDAGOGICAL
LET’S GET REAL(WORLD)
LAZY SEQUENCES PART 1 - THE PLEDGE
STEP WISE PERSON LOOKUP
▸We want to fetch person’s data based
on his email
▸Using Third party services like Clearbit
▸And each lookup for data is expensive
computationally and monetarily.
LAZY SEQUENCES - THE TURN
STEP WISE LOOKUP
def find_match
lookups = [
expensive_phone_lookup(@person.email),
expensive_location_lookup(@person.email),
expensive_property_lookup(@person.email),
]
lookups.each do |lookup|
result = @service.match_person(stage)
break result if result.success?
end
end
LAZY SEQUENCES - THE PRESTIGE
STEP WISE LOOKUP
def stages(email)
@stages ||= Enumerator.new do |enumerator|
# Step 1: Only Phone
phone = expensive_phone_lookup(email)
enumerator.yield(:email_only, :phone => phone)
# Step 2: Only Phone Number
location = expensive_location_lookup(email)
enumerator.yield(:location_only, :location => location)
# Step 3: Only Property
property = expensive_property_lookup(email)
enumerator.yield(:property, :property => property)
# Step 4: All Info
enumerator.yield(:all_info, all_info)
end
end
LAZY SEQUENCES - THE PRESTIGE
STEP WISE LOOKUP
def find_match
while stage = stage(@person.email).next
result = @service.match_person(stage)
break result if result.success?
end
rescue StopIteration => _
# error handling here
end
LAZY LOADING
A DESIGN PATTERN
A DESIGN PATTERN WHERE
LOADING OF OBJECTS IS
DELAYED UNTIL REQUIRED
RUBY HAS PROCS, BUILT
TO STORE AND RUN CODE
WHEN REQUIRED
RUBY HAS MODULES, BUILT
TO WRITE AND INJECT
CODE WHEN REQUIRED
COMBINE THESE TWO AND
YOU CAN BUILD PROGRAMS
THAT ALLOW LAZY LOADING
WE’LL BE LOOKING AT AN
EXCELLENT LIBRARY
WRITTEN IN RUBY ON RAILS
BUT FIRST ! A LITTLE
BACKGROUND INFO
RAILS IS A HUGE
PROJECT !
250,000+
LINES OF
CODE
60,000+
COMMITS
3,200+
CONTRIBUTOR
S
AND HAS A COMPLEX
LOADING AND
INITIALISING MECHANISM
BUT, WITH HIGH
COMPLEXITY COMES
HIGH BOOT UP TIME
SO IN 2010, TO IMPROVE BOOT
TIME, RAILS CHANGED ITS
INITIALISATION MECHANISM
TO LAZY LOADING
https://github.com/rails/rails/commit/39d6f9e112f2320d8c2006ee3bcc160cfa761d0a
AND THAT’S HOW
ACTIVESUPPORT::LAZYLOAD
HOOKS
WAS BORN
ACTIVE SUPPORT LAZY LOAD HOOKS
THE TASK OF THIS LIBRARY IS TO
▸Accept blocks of code and store them
in a hash.
▸Have a calling mechanism for the
stored blocks.
▸Then call those stored blocks when
required.
ACCEPT BLOCKS AND STORE THEM IN A
HASH
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb
CALL THE HOOKS ONLY WHEN REQUIRED
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb
EXECUTE THE STORED BLOCKS
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb
https://github.com/rails/rails/blob/master/activerecord/lib/active_record.rb
ActiveRecord
https://github.com/rails/rails/blob/master/activerecord/lib/active_record.rb
ActiveRecord
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/base.rb
ActiveRecord::Base
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/base.rb
ActiveRecord::Base
ACTIVE SUPPORT LAZY LOAD HOOKS
THE IMPLICATIONS OF THIS LIBRARY ARE
▸By calling the .run_load_hooks
method at the end, Rails can call code
that depends on ActiveRecord, lazily.
▸This helps Rails load code only when
it’s required, which reduces its
booting time significantly.
EXAMPLE
THE CORNERSTONE OF A
NUTRITIOUS RAILS APP
Lazy, Lazy, Lazy all the things !
USER AUTHENTICATION
CURRENT_USER,
REMEMBER?
YOU CAN USE THIS OBJECT
FOR QUERYING, SCOPING, ET
AL; ALL IN THE CONTEXT OF
CONTROLLERS AND VIEWS.
Lazy, Lazy, Lazy all the things !
PASSING THE OBJECT TO
EVERY MODEL METHOD
DOESN’T MAKE SENSE,
RIGHT ?
THE CURRENT USER - THE PLEDGE
‣ All you need to do is store the current_user in
a thread-local variable and use it in your
model
‣ Thread.current[:current_user] =
@current_user
USING CURRENT USER ACROSS THE APP
THE CURRENT USER - THE PLEDGE
USING CURRENT USER ACROSS THE APP
‣ If you’re using threaded app servers like Thin
or Puma, then it’s wise to use the
request_store or request_store_rails gem.
‣ RequestStore.store[:current_user]
= @current_user
SAY YOU HAVE A BLOG
APPLICATION AND YOU WANT
TO SHOW THE CURRENT
USER’S COMMENTS ON A BLOG
THE CURRENT USER - THE PRESTIGE
USING CURRENT USER ACROSS THE APP
class Blog
include Mongoid::Document
field :title, type: String
field :content, type: String
belongs_to :author, class_name: "User"
has_many :comments
attr_accessor :current_viewer
after_initialize Proc.new { |blog|
blog.current_viewer = RequestStore.store[:current_user]
}
def my_comments
self.comments.where(user_id: self.current_viewer.id)
end
end
THE CURRENT USER - THE PRESTIGE
USING CURRENT USER ACROSS THE APP
class Blog
include Mongoid::Document
field :title, type: String
field :content, type: String
belongs_to :author, class_name: "User"
has_many :comments
attr_accessor :current_viewer
after_initialize Proc.new { |blog|
blog.current_viewer = RequestStore.store[:current_user]
}
def my_comments
self.comments.where(user_id: self.current_viewer.id)
end
end
THE CURRENT USER - THE TURN
USING CURRENT USER ACROSS THE APP
module CurrentUser
class RailTie < Rails::RailTie
ActiveSupport.on_load :action_controller do
before_action do |c|
RequestStore.store[:current_user] ||=
c.current_user if c.current_user.present?
end
end
end
end
THE CURRENT USER - THE TURN
USING CURRENT USER ACROSS THE APP
module CurrentUser
class RailTie < Rails::RailTie
ActiveSupport.on_load :action_controller do
before_action do |c|
RequestStore.store[:current_user] ||=
c.current_user if c.current_user.present?
end
end
end
end
ANOTHER EXAMPLE
WE HAVE THE SAME
BLOG APPLICATION, BUT
WITH A FEW CHANGES
class Blog
include Mongoid::Document
field :title, type: String
field :content, type: String
belongs_to :author, class_name: "User"
attr_accessor :current_viewer
after_initialize Proc.new { |blog|
blog.current_viewer = RequestStore.store[:current_user]
}
ActiveSupport.run_load_hooks(:blog, self)
end
class Blog
include Mongoid::Document
field :title, type: String
field :content, type: String
belongs_to :author, class_name: "User"
attr_accessor :current_viewer
after_initialize Proc.new { |blog|
blog.current_viewer = RequestStore.store[:current_user]
}
ActiveSupport.run_load_hooks(:blog, self)
end
WE’VE SEPARATED THE
COMMENTS FEATURE AS
A MODULE
module Commentable
def self.included(base)
base.has_many :comments, as: :commentable
base.send(:include, InstanceMethods)
end
module InstanceMethods
def my_comments
self.comments.where(user_id: self.current_viewer.id)
end
# . . .
end
end
ActiveSupport.on_load(:blog) do
self.send(:include, Commentable)
end
NOW WE’VE DECIDED TO
ADD FEEDS AND PHOTOS
TO THE APP
class Feed
# feed model details here
ActiveSupport.run_load_hooks(:feed, self)
end
class Photo
# feed model details here
ActiveSupport.run_load_hooks(:photo, self)
end
THEY SHOULD SUPPORT
COMMENTS AS WELL
[:blog, :feed, :photo].each do |post|
ActiveSupport.on_load(post) do
self.send(:include, Commentable)
end
end
THERE ARE PLENTY OF
OTHER LAZY PARADIGMS
THERE ARE PLENTY OF
OTHER LAZY LANGUAGES
ENOUGH LAZINESS TODAY
CONCLUSION
||=
IS A HANDY SHORT CIRCUIT
OPERATOR
ENUMERATOR::LAZY
OFFERS INFINITE AND
IMMUTABLE SEQUENCES
ACTIVESUPPORT::LAZYLOADHOOKS
IS A POWERFUL LIBRARY FOR
COMPOSING BEHAVIOUR
THANK YOU !
AMURA MARKETING
TECHNOLOGIES
SHAUNAK PAGNIS
@_kanuahs
shaunakpp
shaunak-amura
SHAUNAK PAGNIS

More Related Content

PDF
The swift programming language
PDF
Front end performance analysis v0.6
PPT
35 hard work and smart work
PPTX
Dynamic Dimension Profile
PPTX
지스타^^
PDF
2016 SFU Pre-Game
PPT
Microsoft Forefront - Secure Endpoint Solution Presentation
PDF
UX Sofia 2012 - DIY Mobile Usability Testing Workshop
The swift programming language
Front end performance analysis v0.6
35 hard work and smart work
Dynamic Dimension Profile
지스타^^
2016 SFU Pre-Game
Microsoft Forefront - Secure Endpoint Solution Presentation
UX Sofia 2012 - DIY Mobile Usability Testing Workshop

Viewers also liked (9)

PPTX
Short film distribution ( version 2 )
PPS
Soldado
PPS
Abortion quick facts
DOC
Anand Jha-Updated CV
PDF
Capital one-mascot-challenge
PPT
Vector Graphics W4
PPTX
презентация Microsoft office power point
PPT
Slide Alimen. Gastr
Short film distribution ( version 2 )
Soldado
Abortion quick facts
Anand Jha-Updated CV
Capital one-mascot-challenge
Vector Graphics W4
презентация Microsoft office power point
Slide Alimen. Gastr
Ad

Similar to Lazy, Lazy, Lazy all the things ! (20)

KEY
Intro to Ruby
PDF
Rails workshop for Java people (September 2015)
PDF
Ruby and Rails by Example (GeekCamp edition)
PDF
Story for a Ruby on Rails Single Engineer
PDF
How to stop being Rails Developer
KEY
SOLID Ruby, SOLID Rails
PDF
Ruby on Rails - Introduction
PDF
A Small Talk on Getting Big
KEY
Stop Reinventing The Wheel - The Ruby Standard Library
KEY
Rails traps
PDF
Refactoring Workshop (Rails Pacific 2014)
PPTX
Day 1 - Intro to Ruby
KEY
Building Web Service Clients with ActiveModel
KEY
Building Web Service Clients with ActiveModel
PDF
Ruby on Rails
PPTX
Rails World 2023: Powerful Rails Features You Might Not Know
KEY
Intro to Ruby - Twin Cities Code Camp 7
PDF
Ruby and rails - Advanced Training (Cybage)
PPTX
RoR guide_p1
PDF
Perusing the Rails Source Code
Intro to Ruby
Rails workshop for Java people (September 2015)
Ruby and Rails by Example (GeekCamp edition)
Story for a Ruby on Rails Single Engineer
How to stop being Rails Developer
SOLID Ruby, SOLID Rails
Ruby on Rails - Introduction
A Small Talk on Getting Big
Stop Reinventing The Wheel - The Ruby Standard Library
Rails traps
Refactoring Workshop (Rails Pacific 2014)
Day 1 - Intro to Ruby
Building Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModel
Ruby on Rails
Rails World 2023: Powerful Rails Features You Might Not Know
Intro to Ruby - Twin Cities Code Camp 7
Ruby and rails - Advanced Training (Cybage)
RoR guide_p1
Perusing the Rails Source Code
Ad

Recently uploaded (20)

PPTX
Trending Python Topics for Data Visualization in 2025
PPTX
Cybersecurity: Protecting the Digital World
PPTX
Airline CRS | Airline CRS Systems | CRS System
PDF
Practical Indispensable Project Management Tips for Delivering Successful Exp...
DOCX
Modern SharePoint Intranet Templates That Boost Employee Engagement in 2025.docx
PPTX
WiFi Honeypot Detecscfddssdffsedfseztor.pptx
PDF
DNT Brochure 2025 – ISV Solutions @ D365
PDF
Guide to Food Delivery App Development.pdf
PPTX
"Secure File Sharing Solutions on AWS".pptx
PDF
Salesforce Agentforce AI Implementation.pdf
PPTX
CNN LeNet5 Architecture: Neural Networks
PDF
The Dynamic Duo Transforming Financial Accounting Systems Through Modern Expe...
DOCX
How to Use SharePoint as an ISO-Compliant Document Management System
PDF
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
PDF
Top 10 Software Development Trends to Watch in 2025 🚀.pdf
PPTX
most interesting chapter in the world ppt
PDF
Autodesk AutoCAD Crack Free Download 2025
PPTX
Computer Software - Technology and Livelihood Education
PDF
Multiverse AI Review 2025: Access All TOP AI Model-Versions!
PDF
AI/ML Infra Meetup | LLM Agents and Implementation Challenges
Trending Python Topics for Data Visualization in 2025
Cybersecurity: Protecting the Digital World
Airline CRS | Airline CRS Systems | CRS System
Practical Indispensable Project Management Tips for Delivering Successful Exp...
Modern SharePoint Intranet Templates That Boost Employee Engagement in 2025.docx
WiFi Honeypot Detecscfddssdffsedfseztor.pptx
DNT Brochure 2025 – ISV Solutions @ D365
Guide to Food Delivery App Development.pdf
"Secure File Sharing Solutions on AWS".pptx
Salesforce Agentforce AI Implementation.pdf
CNN LeNet5 Architecture: Neural Networks
The Dynamic Duo Transforming Financial Accounting Systems Through Modern Expe...
How to Use SharePoint as an ISO-Compliant Document Management System
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
Top 10 Software Development Trends to Watch in 2025 🚀.pdf
most interesting chapter in the world ppt
Autodesk AutoCAD Crack Free Download 2025
Computer Software - Technology and Livelihood Education
Multiverse AI Review 2025: Access All TOP AI Model-Versions!
AI/ML Infra Meetup | LLM Agents and Implementation Challenges

Lazy, Lazy, Lazy all the things !