Module: Lab42::Stream::Enumerable

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

Instance Method Summary collapse

Instance Method Details

#__drop_while__(bhv) ⇒ Object



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

def __drop_while__ bhv
  s = self
  loop do
    return s unless bhv.(s.head)
    s = s.tail
  end
  empty_stream
end

#__filter__(stream, a_proc) ⇒ Object



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

def __filter__ stream, a_proc
  loop do
    return stream if stream.empty?
    return cons_stream( stream.head ){ __filter__ stream.tail, a_proc } if a_proc.( stream.head )
    stream = stream.tail
  end
end

#__flatmap__(a_proc) ⇒ Object

Raises:

  • (ArgumentError)


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

def __flatmap__ a_proc
  hh = a_proc.( head )
  raise ArgumentError, "flatmap can only map on streams, use flatmap_with_each to map over streams and enumerables" unless
    Lab42::Stream === hh
  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



253
254
255
256
# File 'lib/lab42/stream/enumerable.rb', line 253

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:



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

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



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

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

#__scan__(initial, beh) ⇒ Object



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

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

#__take_while__(bhv) ⇒ Object



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

def __take_while__ bhv
  x = []
  each do | ele |
    return x unless bhv.( ele )
    x << ele
  end
  x
end

#__zip__(streams) ⇒ Object



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

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

#drop_until(*bhv, &blk) ⇒ Object



10
11
12
13
# File 'lib/lab42/stream/enumerable.rb', line 10

def drop_until *bhv, &blk
  bhv = Behavior.make( *bhv, &blk )
  __drop_while__ bhv.not
end

#drop_while(*bhv, &blk) ⇒ Object



15
16
17
18
# File 'lib/lab42/stream/enumerable.rb', line 15

def drop_while *bhv, &blk
  bhv = Behavior.make( *bhv, &blk )
  __drop_while__ bhv
end

#eachObject



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

def each
  t = self
  loop do
    return if t.empty?
    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__ self, Behavior.make( *args, &blk )
end

#flatmap(*args, &blk) ⇒ Object



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

def flatmap *args, &blk
  __flatmap__ Behavior.make( *args, &blk )
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__ Behavior.make( *args, &blk )
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, Behavior.make( *red, &reducer )
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 Integer" if !(Integer === 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 = Behavior.make( *bhv, &blk )
  __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 = Behavior.make( *bhv, &blk )
  __lazy_take_while__ bhv
end

#make_cyclicObject



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

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

#map(*args, &blk) ⇒ Object

Raises:

  • (ArgumentError)


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

def map *args, &blk
  raise ArgumentError, "use either a block or arguments" if args.empty? && !blk || !args.empty? && blk
  __map__ Behavior.make( *args, &blk )
end

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



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

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

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



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

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__ self, Behavior.make( *args, &blk ).not
end

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



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

def scan initial, *args, &blk
  cons_stream initial do
    __scan__ initial, Behavior.make( *args, &blk )
  end.tap{ |r|
  }
end

#scan1(*args, &blk) ⇒ Object



161
162
163
# File 'lib/lab42/stream/enumerable.rb', line 161

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

#take(n = 1) ⇒ Object

Raises:

  • (ArgumentError)


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

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

#take_until(*bhv, &blk) ⇒ Object



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

def take_until *bhv, &blk
  bhv = Behavior.make( *bhv, &blk )
  __take_while__ bhv.not
end

#take_while(*bhv, &blk) ⇒ Object



175
176
177
178
# File 'lib/lab42/stream/enumerable.rb', line 175

def take_while *bhv, &blk
  bhv = Behavior.make( *bhv, &blk )
  __take_while__ bhv
end

#to_aObject Also known as: entries



189
190
191
# File 'lib/lab42/stream/enumerable.rb', line 189

def to_a
  take_while Behavior.const( true ) 
end

#zip(*other_streamables) ⇒ Object



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

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



234
235
236
237
# File 'lib/lab42/stream/enumerable.rb', line 234

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