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



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

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



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

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



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

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



255
256
257
258
# File 'lib/lab42/stream/enumerable.rb', line 255

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:



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

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



71
72
73
74
# File 'lib/lab42/stream/enumerable.rb', line 71

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

#__lazy_take_until__(bhv) ⇒ Object



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

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



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

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

#__map__(prc) ⇒ Object



208
209
210
# File 'lib/lab42/stream/enumerable.rb', line 208

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

#__scan__(initial, beh) ⇒ Object



167
168
169
170
# File 'lib/lab42/stream/enumerable.rb', line 167

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

#__zip__(streams) ⇒ Object



241
242
243
244
245
# File 'lib/lab42/stream/enumerable.rb', line 241

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

#drop_until(*bhv, &blk) ⇒ Object



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

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



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

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



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

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

#each_without_loopsObject



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

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



109
110
111
# File 'lib/lab42/stream/enumerable.rb', line 109

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

#flatmap(*args, &blk) ⇒ Object



117
118
119
# File 'lib/lab42/stream/enumerable.rb', line 117

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

#flatmap_with_each(*args, &blk) ⇒ Object



132
133
134
# File 'lib/lab42/stream/enumerable.rb', line 132

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

#force_all(cache = {}) ⇒ Object



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

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



105
106
107
# File 'lib/lab42/stream/enumerable.rb', line 105

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

#lazy_take(n = 1) ⇒ Object

Raises:

  • (ArgumentError)


66
67
68
69
# File 'lib/lab42/stream/enumerable.rb', line 66

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



76
77
78
79
# File 'lib/lab42/stream/enumerable.rb', line 76

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

#lazy_take_while(*bhv, &blk) ⇒ Object



88
89
90
91
# File 'lib/lab42/stream/enumerable.rb', line 88

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

#make_cyclicObject



196
197
198
199
200
# File 'lib/lab42/stream/enumerable.rb', line 196

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

#map(*args, &blk) ⇒ Object

Raises:

  • (ArgumentError)


202
203
204
205
206
# File 'lib/lab42/stream/enumerable.rb', line 202

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



100
101
102
103
# File 'lib/lab42/stream/enumerable.rb', line 100

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

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



213
214
215
216
# File 'lib/lab42/stream/enumerable.rb', line 213

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

#reject(*args, &blk) ⇒ Object



113
114
115
# File 'lib/lab42/stream/enumerable.rb', line 113

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

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



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

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



163
164
165
# File 'lib/lab42/stream/enumerable.rb', line 163

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

#take(n = 1) ⇒ Object

Raises:

  • (ArgumentError)


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

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



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

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



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

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



191
192
193
# File 'lib/lab42/stream/enumerable.rb', line 191

def to_a
  take_while :true
end

#zip(*other_streamables) ⇒ Object



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

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



236
237
238
239
# File 'lib/lab42/stream/enumerable.rb', line 236

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