Lazy Mixin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# Before you ask--yes, this has a very specific use case and is not # generally applicable to the problem of fine-grained lazy evaluation. # But it does *exactly* what I need it to do. =) # Allows attributes to be declared as lazy, meaning that they won't be # computed until they are asked for. Just mix this module in: # # class Foo # include Lazy # ... # end # # To specify a lazy reader: # # lazy_reader :att # # Then, define a method called __bake__ that computes all your lazy # attributes: # # def __bake__ # @att = ... # end # # That's it! (Tom Preston-Werner: rubyisawesome.com) module Lazy module ClassMethods def lazy_reader(*args) args.each do |arg| define_method(arg) do self.__prebake__ instance_variable_get(('@' + arg.to_s).intern) end end end end def __prebake__ return if @__baked__ self.__bake__ @__baked__ = true end def self.included(base) base.extend(ClassMethods) end end # A pedagogical class with a lazy attribute class Foo include Lazy attr_reader :id lazy_reader :body def initialize(id) @id = id end def __bake__ puts "__baking__" @body = "The 30th fibonacci is #{self.fib(30)}" end def fib(n) return 1 if n == 0 || n == 1 return fib(n-1) + fib(n-2) end end t = Foo.new('abc') puts t.id # => (immediate) "abc" puts t.body # => (short pause) The 30th fibonacci is 1346269 puts t.body # => (immediate) The 30th fibonacci is 1346269 |
About this entry
You’re currently reading “Lazy Mixin,” an entry on Ruby is Awesome

- Published:
- October 12th 11:40 PM
- Updated:
- October 12th 11:41 PM
- Sections:
1 comment
Jump to comment form | comments rss [?]