Module: Lab42::Stream::Enumerable

Included in:
Lab42::Stream
Defined in:
lib/lab42/stream/enumerable.rb

Instance Method Summary collapse

Instance Method Details

#__filter__(a_proc) ⇒ Object



249
250
251
252
253
254
255
# File 'lib/lab42/stream/enumerable.rb', line 249

def __filter__ a_proc
  if a_proc.( head )
    cons_stream( head ){ tail.__filter__ a_proc } 
  else
    tail.__filter__ a_proc
  end
end

#__flatmap__(a_proc) ⇒ Object



123
124
125
126
127
128
129
130
131
132
# File 'lib/lab42/stream/enumerable.rb', line 123

def __flatmap__ a_proc
  # require 'pry'
  # binding.pry
  hh = a_proc.( head )
  if hh.empty?
    tail.__flatmap__ a_proc
  else
    cons_stream( hh.head ){ hh.tail + tail.__flatmap__( a_proc ) }
  end
end

#__flatmap_with_each__(a_proc, rest_of_enum = []) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/lab42/stream/enumerable.rb', line 138

def __flatmap_with_each__ a_proc, rest_of_enum = []
  # Process expanded values
  return cons_stream( rest_of_enum.first ){ __flatmap_with_each__ a_proc, rest_of_enum.drop( 1 ) } unless
    rest_of_enum.empty?

  # Map a scalar value
  hh = a_proc.( head )
  return cons_stream( hh ){ tail.__flatmap_with_each__ a_proc } unless
    hh.respond_to? :each

  # Start a new expansion...
  # ... consider an empty expansion
  return tail.__flatmap__ a_proc if hh.empty?
  # ... expand values
  cons_stream( hh.first ){ tail.__flatmap_with_each__( a_proc, hh.drop( 1 ) ) }
end

#__inject__(agg, a_proc) ⇒ Object



257
258
259
260
# File 'lib/lab42/stream/enumerable.rb', line 257

def __inject__ agg, a_proc
  new_agg = a_proc.(agg, head)
  tail.__inject__ new_agg, a_proc
end

#__inject_while__(ival, cond, red) ⇒ Object

Raises:



262
263
264
265
266
267
268
269
270
271
272
# File 'lib/lab42/stream/enumerable.rb', line 262

def __inject_while__ ival, cond, red
  raise ConstraintError unless cond.(ival)
  s = self
  loop do
    new_val = red.(ival, s.head)
    return ival unless cond.(new_val)
    ival = new_val
    s = s.tail
    return ival if s.empty?
  end
end

#__lazy_take__(n) ⇒ Object



73
74
75
76
# File 'lib/lab42/stream/enumerable.rb', line 73

def __lazy_take__ n
  return empty_stream if n.zero?
  cons_stream( head ){ tail.__lazy_take__ n.pred }
end

#__lazy_take_until__(bhv) ⇒ Object



83
84
85
86
87
88
# File 'lib/lab42/stream/enumerable.rb', line 83

def __lazy_take_until__ bhv
  return empty_stream if bhv.(head)
  cons_stream( head ){
    tail.__lazy_take_until__ bhv
  }
end

#__lazy_take_while__(bhv) ⇒ Object



95
96
97
98
99
100
# File 'lib/lab42/stream/enumerable.rb', line 95

def __lazy_take_while__ bhv
  return empty_stream unless bhv.(head)
  cons_stream( head ){
    tail.__lazy_take_while__ bhv
  }
end

#__map__(prc) ⇒ Object



210
211
212
# File 'lib/lab42/stream/enumerable.rb', line 210

def __map__ prc
  cons_stream( prc.(head) ){ tail.__map__ prc }
end

#__scan__(initial, beh) ⇒ Object



169
170
171
172
# File 'lib/lab42/stream/enumerable.rb', line 169

def __scan__ initial, beh
  h = beh.(initial, head)
  cons_stream( h ){ tail.__scan__ h, beh }
end

#__zip__(streams) ⇒ Object



243
244
245
246
247
# File 'lib/lab42/stream/enumerable.rb', line 243

def __zip__ streams
  cons_stream( [head] + streams.map(:head) ){
    tail.__zip__ streams.map(:tail)
  }
end

#drop_until(*bhv, &blk) ⇒ Object



11
12
13
14
15
16
17
18
19
# File 'lib/lab42/stream/enumerable.rb', line 11

def drop_until *bhv, &blk
  bhv = blk.make_behavior( *bhv )
  s = self
  loop do
    return s if bhv.(s.head)
    s = s.tail
  end
  empty_stream
end

#drop_while(*bhv, &blk) ⇒ Object

N.B. Not implemented as drop_until( bhv.not ) for performance reasons



23
24
25
26
27
28
29
30
31
# File 'lib/lab42/stream/enumerable.rb', line 23

def drop_while *bhv, &blk
  bhv = blk.make_behavior( *bhv )
  s = self
  loop do
    return s unless bhv.(s.head)
    s = s.tail
  end
  empty_stream
end

#eachObject



33
34
35
36
37
38
39
# File 'lib/lab42/stream/enumerable.rb', line 33

def each
  t = self
  loop do
    yield t.head
    t = t.tail
  end
end

#each_without_loopsObject



41
42
43
44
45
46
47
48
49
50
51
# File 'lib/lab42/stream/enumerable.rb', line 41

def each_without_loops
  visited = {}
  t = self
  loop do
    h = t.head
    yield h
    visited[ t.object_id ] = true
    t = t.tail
    return if visited[t.object_id]
  end
end

#filter(*args, &blk) ⇒ Object



111
112
113
# File 'lib/lab42/stream/enumerable.rb', line 111

def filter *args, &blk
  __filter__ blk.make_behavior( *args )
end

#flatmap(*args, &blk) ⇒ Object



119
120
121
# File 'lib/lab42/stream/enumerable.rb', line 119

def flatmap *args, &blk
  __flatmap__ blk.make_behavior( *args )
end

#flatmap_with_each(*args, &blk) ⇒ Object



134
135
136
# File 'lib/lab42/stream/enumerable.rb', line 134

def flatmap_with_each *args, &blk
  __flatmap_with_each__ blk.make_behavior( *args )
end

#force_all(cache = {}) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/lab42/stream/enumerable.rb', line 53

def force_all cache={}
  x = []
  each_without_loops do | ele |
    if self.class === ele
      if ! cache[ele.object_id]
        cache[ele.object_id] = true
        x << ele.force_all( cache )
      end
    else
      x << ele
    end
  end
  x
end

#inject(agg, *red, &reducer) ⇒ Object



107
108
109
# File 'lib/lab42/stream/enumerable.rb', line 107

def inject agg, *red, &reducer
  __inject__ agg, reducer.make_behavior( *red )
end

#lazy_take(n = 1) ⇒ Object

Raises:

  • (ArgumentError)


68
69
70
71
# File 'lib/lab42/stream/enumerable.rb', line 68

def lazy_take n=1
  raise ArgumentError, "need a non negative Fixnum" if !(Fixnum === n) || n < 0
  __lazy_take__ n
end

#lazy_take_until(*bhv, &blk) ⇒ Object



78
79
80
81
# File 'lib/lab42/stream/enumerable.rb', line 78

def lazy_take_until *bhv, &blk
  bhv = blk.make_behavior( *bhv )
  __lazy_take_until__ bhv
end

#lazy_take_while(*bhv, &blk) ⇒ Object



90
91
92
93
# File 'lib/lab42/stream/enumerable.rb', line 90

def lazy_take_while *bhv, &blk
  bhv = blk.make_behavior( *bhv )
  __lazy_take_while__ bhv
end

#make_cyclicObject



198
199
200
201
202
# File 'lib/lab42/stream/enumerable.rb', line 198

def make_cyclic
  cons_stream( head ){
    tail.append( make_cyclic )
  }
end

#map(*args, &blk) ⇒ Object

Raises:

  • (ArgumentError)


204
205
206
207
208
# File 'lib/lab42/stream/enumerable.rb', line 204

def map *args, &blk
  # TODO: Get this check and a factory to create a proc for this into core/fn
  raise ArgumentError, "use either a block or arguments" if args.empty? && !blk || !args.empty? && blk
  __map__ blk.make_behavior( *args )
end

#reduce(red = nil, &reducer) ⇒ Object



102
103
104
105
# File 'lib/lab42/stream/enumerable.rb', line 102

def reduce red=nil, &reducer
  red = reducer.make_behavior( red )
  tail.__inject__ head, red
end

#reduce_while(cond, red = nil, &reducer) ⇒ Object



215
216
217
218
# File 'lib/lab42/stream/enumerable.rb', line 215

def reduce_while cond, red=nil, &reducer
  red ||= reducer
  tail.__inject_while__ head, cond, red
end

#reject(*args, &blk) ⇒ Object



115
116
117
# File 'lib/lab42/stream/enumerable.rb', line 115

def reject *args, &blk
  __filter__ blk.make_behavior( *args ).not
end

#scan(initial, *args, &blk) ⇒ Object



156
157
158
159
160
161
162
163
# File 'lib/lab42/stream/enumerable.rb', line 156

def scan initial, *args, &blk
  cons_stream initial do
    __scan__ initial, blk.make_behavior( *args )
  end.tap{ |r|
    # require 'pry'
    # binding.pry
  }
end

#scan1(*args, &blk) ⇒ Object



165
166
167
# File 'lib/lab42/stream/enumerable.rb', line 165

def scan1 *args, &blk
  tail.scan( head, *args, &blk )
end

#take(n = 1) ⇒ Object

Raises:

  • (ArgumentError)


220
221
222
223
224
225
226
227
228
229
# File 'lib/lab42/stream/enumerable.rb', line 220

def take n=1
  raise ArgumentError, "need a non negative Fixnum" if !(Fixnum === n) || n < 0
  x = []
  each do | ele |
    return x if n.zero?
    n -= 1
    x << ele
  end
  x
end

#take_until(*bhv, &blk) ⇒ Object



174
175
176
177
178
179
180
181
182
# File 'lib/lab42/stream/enumerable.rb', line 174

def take_until *bhv, &blk
  bhv = blk.make_behavior( *bhv )
  x = []
  each do | ele |
    return x if bhv.( ele )
    x << ele
  end
  x
end

#take_while(*bhv, &blk) ⇒ Object



183
184
185
186
187
188
189
190
191
# File 'lib/lab42/stream/enumerable.rb', line 183

def take_while *bhv, &blk
  bhv = blk.make_behavior( *bhv )
  x = []
  each do | ele |
    return x unless bhv.( ele )
    x << ele
  end
  x
end

#to_aObject Also known as: entries



193
194
195
# File 'lib/lab42/stream/enumerable.rb', line 193

def to_a
  take_while :true
end

#zip(*other_streamables) ⇒ Object



231
232
233
234
235
236
# File 'lib/lab42/stream/enumerable.rb', line 231

def zip *other_streamables
  streams = other_streamables.map{ |s|
    self.class === s ? s : s.to_stream
  }
  __zip__ streams
end

#zip_as_ary(*other_streamables) ⇒ Object



238
239
240
241
# File 'lib/lab42/stream/enumerable.rb', line 238

def zip_as_ary *other_streamables
  zip( *other_streamables )
    .map( &:entries )
end