Class: Lazy::LazyEnumerable

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/lazy/lazy_enumerable.rb

Constant Summary collapse

PLACEBO =
lambda {|each| each}

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(proc) ⇒ LazyEnumerable

Returns a new instance of LazyEnumerable.



44
45
46
47
# File 'lib/lazy/lazy_enumerable.rb', line 44

def initialize(proc)
  @internal=proc
  @sends=[]
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *arguments) ⇒ Object

Simply make a closure around the method and capturing it’s arguments as well This is so it can be replayed. Notice again, I cache the method with a define_method



53
54
55
56
57
58
59
60
61
# File 'lib/lazy/lazy_enumerable.rb', line 53

def method_missing(method_name, *arguments)
  proc=lambda do |*args|
    send=lambda {|each| each.send(method_name, *args)}
    @sends << send
    self
  end
  self._class.send(:define_method, method_name, &proc)
  proc.call(*arguments)
end

Class Method Details

.iterator_creator(*method_names) ⇒ Object



29
30
31
# File 'lib/lazy/lazy_enumerable.rb', line 29

def self.iterator_creator(*method_names)
  method_names.each { |every| iterator_creator_for(every) }
end

.iterator_creator_for(method_name) ⇒ Object



33
34
35
36
# File 'lib/lazy/lazy_enumerable.rb', line 33

def self.iterator_creator_for(method_name)
  non_lazy_name = /lazy_(.+)/.match(method_name.to_s)[1].to_sym
  define_method(method_name) { LazyEnumerable.new(_method(non_lazy_name)) }
end

.wack_all_my_methodsObject

Remove any unnecessary methods so that method_missing is invoked



19
20
21
22
23
24
25
26
27
# File 'lib/lazy/lazy_enumerable.rb', line 19

def self.wack_all_my_methods
  to_wack = instance_methods.reject do |each|
    ['===','method_missing'].include?(each) || each =~ /^__/
  end
  to_wack.each do |each|
    alias_method("_#{each}", each)
    undef_method(each)
  end
end

Instance Method Details

#each(&block) ⇒ Object

Call each member in the original collection and call each “captured” method in succession. Notice the use of inject to make this really elegant and succint. I do cheat a little and realize the collection and then call each. I want to change this in the future. Actually, 1.9 will make this possible. We’ll be able to use iterators and will make below more lazy.



81
82
83
84
85
86
87
88
# File 'lib/lazy/lazy_enumerable.rb', line 81

def each(&block)
  answer = @internal.call do |each|
    @sends.inject(each) do |result, each_send |
      each_send.call(result)
    end
  end
  answer.each(&block)
end

#respond_to?(symbol, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


63
64
65
# File 'lib/lazy/lazy_enumerable.rb', line 63

def respond_to?(symbol,include_private = false)
  true
end

#sizeObject

Give me the size. This can be dangerous if you ever wrap an infinite enumerable



93
94
95
# File 'lib/lazy/lazy_enumerable.rb', line 93

def size
  inject(0) {|sum,each| sum + 1 }
end

#to_lazyObject



97
98
99
# File 'lib/lazy/lazy_enumerable.rb', line 97

def to_lazy
  self
end

#to_realObject

Do a placebo collect to get it to create an array with the elements



70
71
72
# File 'lib/lazy/lazy_enumerable.rb', line 70

def to_real
  collect(&PLACEBO)
end