reacto 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/README.md +932 -11
  4. data/doc/reactive_programming_with_reacto.md +238 -0
  5. data/lib/reacto.rb +70 -0
  6. data/lib/reacto/behaviours.rb +24 -1
  7. data/lib/reacto/constants.rb +4 -1
  8. data/lib/reacto/executors.rb +8 -10
  9. data/lib/reacto/labeled_trackable.rb +14 -2
  10. data/lib/reacto/operations.rb +23 -2
  11. data/lib/reacto/operations/act.rb +69 -0
  12. data/lib/reacto/operations/append.rb +45 -0
  13. data/lib/reacto/operations/blocking_enumerable.rb +40 -0
  14. data/lib/reacto/operations/buffer.rb +1 -4
  15. data/lib/reacto/operations/chunk.rb +81 -0
  16. data/lib/reacto/operations/chunk_while.rb +56 -0
  17. data/lib/reacto/operations/cycle.rb +27 -0
  18. data/lib/reacto/operations/delay_each.rb +75 -0
  19. data/lib/reacto/operations/depend_on.rb +4 -5
  20. data/lib/reacto/operations/diff.rb +8 -10
  21. data/lib/reacto/operations/drop.rb +6 -8
  22. data/lib/reacto/operations/drop_while.rb +23 -0
  23. data/lib/reacto/operations/each_collect.rb +57 -0
  24. data/lib/reacto/operations/each_with_object.rb +31 -0
  25. data/lib/reacto/operations/extremums.rb +54 -0
  26. data/lib/reacto/operations/find_index.rb +28 -0
  27. data/lib/reacto/operations/flat_map.rb +2 -2
  28. data/lib/reacto/operations/flatten.rb +2 -7
  29. data/lib/reacto/operations/flatten_labeled.rb +44 -0
  30. data/lib/reacto/operations/{label.rb → group_by_label.rb} +1 -1
  31. data/lib/reacto/operations/include.rb +40 -0
  32. data/lib/reacto/operations/inject.rb +15 -9
  33. data/lib/reacto/operations/map.rb +15 -13
  34. data/lib/reacto/operations/merge.rb +17 -16
  35. data/lib/reacto/operations/operation_on_labeled.rb +29 -0
  36. data/lib/reacto/operations/partition.rb +52 -0
  37. data/lib/reacto/operations/prepend.rb +0 -3
  38. data/lib/reacto/operations/rescue_and_replace_error.rb +21 -0
  39. data/lib/reacto/operations/retry.rb +26 -0
  40. data/lib/reacto/operations/retry_when.rb +30 -0
  41. data/lib/reacto/operations/select.rb +2 -6
  42. data/lib/reacto/operations/slice.rb +50 -0
  43. data/lib/reacto/operations/slice_when.rb +41 -0
  44. data/lib/reacto/operations/split_labeled.rb +32 -0
  45. data/lib/reacto/operations/take.rb +9 -14
  46. data/lib/reacto/operations/take_while.rb +28 -0
  47. data/lib/reacto/operations/throttle.rb +2 -3
  48. data/lib/reacto/operations/track_on.rb +1 -3
  49. data/lib/reacto/shared_trackable.rb +2 -5
  50. data/lib/reacto/subscriptions/buffered_subscription.rb +10 -9
  51. data/lib/reacto/subscriptions/executor_subscription.rb +12 -4
  52. data/lib/reacto/subscriptions/tracker_subscription.rb +0 -4
  53. data/lib/reacto/subscriptions/zipping_subscription.rb +0 -1
  54. data/lib/reacto/trackable.rb +429 -64
  55. data/lib/reacto/version.rb +1 -1
  56. data/reacto.gemspec +2 -3
  57. data/spec/reacto/labeled_trackable_spec.rb +17 -0
  58. data/spec/reacto/trackable/act_spec.rb +15 -0
  59. data/spec/reacto/trackable/all_spec.rb +38 -0
  60. data/spec/reacto/trackable/any_spec.rb +39 -0
  61. data/spec/reacto/trackable/append_spec.rb +38 -0
  62. data/spec/reacto/trackable/buffer_spec.rb +11 -15
  63. data/spec/reacto/trackable/chunk_spec.rb +86 -0
  64. data/spec/reacto/trackable/chunk_while_spec.rb +22 -0
  65. data/spec/reacto/trackable/class_level/combine_last_spec.rb +1 -3
  66. data/spec/reacto/trackable/class_level/interval_spec.rb +4 -6
  67. data/spec/reacto/trackable/class_level/make_spec.rb +0 -15
  68. data/spec/reacto/trackable/{zip_spec.rb → class_level/zip_spec.rb} +0 -2
  69. data/spec/reacto/trackable/concat_spec.rb +12 -12
  70. data/spec/reacto/trackable/count_spec.rb +38 -0
  71. data/spec/reacto/trackable/cycle_spec.rb +14 -0
  72. data/spec/reacto/trackable/delay_each_spec.rb +18 -0
  73. data/spec/reacto/trackable/depend_on_spec.rb +6 -9
  74. data/spec/reacto/trackable/diff_spec.rb +3 -5
  75. data/spec/reacto/trackable/drop_errors_spec.rb +1 -3
  76. data/spec/reacto/trackable/drop_while_spec.rb +15 -0
  77. data/spec/reacto/trackable/each_cons_spec.rb +53 -0
  78. data/spec/reacto/trackable/each_slice_spec.rb +37 -0
  79. data/spec/reacto/trackable/each_with_index_spec.rb +33 -0
  80. data/spec/reacto/trackable/each_with_object_spec.rb +26 -0
  81. data/spec/reacto/trackable/entries_spec.rb +25 -0
  82. data/spec/reacto/trackable/execute_on_spec.rb +33 -0
  83. data/spec/reacto/trackable/find_index_spec.rb +31 -0
  84. data/spec/reacto/trackable/find_spec.rb +34 -0
  85. data/spec/reacto/trackable/first_spec.rb +36 -0
  86. data/spec/reacto/trackable/flat_map_latest_spec.rb +5 -5
  87. data/spec/reacto/trackable/flat_map_spec.rb +25 -0
  88. data/spec/reacto/trackable/flatten_labeled_spec.rb +48 -0
  89. data/spec/reacto/trackable/grep_spec.rb +29 -0
  90. data/spec/reacto/trackable/grep_v_spec.rb +23 -0
  91. data/spec/reacto/trackable/{label_spec.rb → group_by_label_spec.rb} +4 -11
  92. data/spec/reacto/trackable/include_spec.rb +23 -0
  93. data/spec/reacto/trackable/inject_spec.rb +30 -4
  94. data/spec/reacto/trackable/lift_spec.rb +1 -3
  95. data/spec/reacto/trackable/map_spec.rb +17 -3
  96. data/spec/reacto/trackable/max_by_spec.rb +12 -0
  97. data/spec/reacto/trackable/max_spec.rb +19 -0
  98. data/spec/reacto/trackable/merge_spec.rb +6 -7
  99. data/spec/reacto/trackable/min_by_spec.rb +12 -0
  100. data/spec/reacto/trackable/min_spec.rb +19 -0
  101. data/spec/reacto/trackable/minmax_by_spec.rb +12 -0
  102. data/spec/reacto/trackable/minmax_spec.rb +19 -0
  103. data/spec/reacto/trackable/none_spec.rb +38 -0
  104. data/spec/reacto/trackable/on_spec.rb +11 -4
  105. data/spec/reacto/trackable/one_spec.rb +38 -0
  106. data/spec/reacto/trackable/partition_spec.rb +23 -0
  107. data/spec/reacto/trackable/prepend_spec.rb +1 -3
  108. data/spec/reacto/trackable/reject_spec.rb +21 -0
  109. data/spec/reacto/trackable/rescue_and_replace_error_spec.rb +48 -0
  110. data/spec/reacto/trackable/rescue_and_replace_error_with_spec.rb +26 -0
  111. data/spec/reacto/trackable/retry_spec.rb +50 -0
  112. data/spec/reacto/trackable/retry_when_spec.rb +33 -0
  113. data/spec/reacto/trackable/select_spec.rb +18 -7
  114. data/spec/reacto/trackable/slice_after_spec.rb +38 -0
  115. data/spec/reacto/trackable/slice_before_spec.rb +38 -0
  116. data/spec/reacto/trackable/slice_when_spec.rb +26 -0
  117. data/spec/reacto/trackable/sort_by_spec.rb +16 -0
  118. data/spec/reacto/trackable/sort_spec.rb +23 -0
  119. data/spec/reacto/trackable/split_labeled_spec.rb +37 -0
  120. data/spec/reacto/trackable/take_while_spec.rb +16 -0
  121. data/spec/reacto/trackable/throttle_spec.rb +2 -3
  122. data/spec/reacto/trackable/track_on_spec.rb +2 -3
  123. data/spec/reacto/trackable/uniq_spec.rb +2 -4
  124. data/spec/support/helpers.rb +9 -1
  125. metadata +135 -25
  126. data/Gemfile.lock +0 -32
  127. data/lib/reacto/operations/cache.rb +0 -53
  128. data/spec/reacto/trackable/cache_spec.rb +0 -64
@@ -0,0 +1,238 @@
1
+ # Reactive programming with Reacto
2
+
3
+ ## Reactive programming
4
+
5
+ Reactive programming is a buzzword these days. Many think it is something
6
+ really complex and new, but in reality it is very simple thing.
7
+ It creates applications which know when and how to react to changes.
8
+ These changes could be outside ones - from some data source or another application,
9
+ or inside ones - parts of the application depend on other parts and react to
10
+ changes in them.
11
+
12
+ Reactive programming can be achieved by building the right dependencies between
13
+ applications, sources of data, or modules of applications and logic around
14
+ these dependencies -> the changes in all the modules/sources should be propagated
15
+ to the interested modules. There are frameworks and languages that do that
16
+ for us, there are different implementations of that too. In ruby we have
17
+ [RxRuby](https://github.com/ReactiveX/RxRuby), [Frappuccino](https://github.com/steveklabnik/frappuccino) and
18
+ now - Reacto.
19
+
20
+ The truth is that the way Reacto implements its _Reactive programming_ is by
21
+ implementing a not so complex design pattern. In this document we'll introduce it
22
+ and compare it to another pattern, which we already know.
23
+
24
+ ## Patterns
25
+
26
+ ### Enumerator
27
+
28
+ Using Reacto is basically using a specific programming pattern.
29
+ It even looks like a familiar one - the `Enumerator` (or Iterator).
30
+ We can call `each` on any `Enumerable` in Ruby and we'll get
31
+ an `Enumerator`. Then we can call `next` on it to _pull_ values.
32
+
33
+ ```ruby
34
+ enumerator = [1, 2, 3].each
35
+ p enumerator.next # 1
36
+ p enumerator.next # 2
37
+ p enumerator.next # 3
38
+ p enumerator.next # a StopIteration error will be raised
39
+ ```
40
+
41
+ It is more common to pass a *block* to `each`, which will be called for every
42
+ `next` value and the exception will be avoided.
43
+
44
+ ```ruby
45
+ [1, 2, 3].each { |value| p value }
46
+ ```
47
+
48
+ Lastly we can create our own implementations of `Enumerator`. For example
49
+ one that generates infinite sequential integer values, beginning
50
+ from zero.
51
+
52
+ ```ruby
53
+ enumerator = Enumerator.new do |yielder|
54
+ n = 0
55
+
56
+ loop do
57
+ yielder << n
58
+ n = n + 1
59
+ end
60
+ end
61
+
62
+ p enumerator.next # 1
63
+ p enumerator.next # 2
64
+ p enumerator.next # 3
65
+ # .....
66
+ ```
67
+
68
+ OK so we can look at the `Enumerator` as a behavior or a source which
69
+ produces values _on demand_. We _pull_ values from it.
70
+
71
+ ### Reacto::Trackable
72
+
73
+ The central abstraction in Reacto is the `Trackable`. It, like the `Enumerator` implements
74
+ a pattern. An instance can be created depending on the underlying behaviour
75
+ or data source using different methods. As with the `Enumerator` we can
76
+ create a `Reacto::Trackable` using an `Enumerable`.
77
+
78
+ ```ruby
79
+ trackable = Reacto::Trackable.enumerable([1, 2, 3])
80
+ ```
81
+
82
+ Now we can track for values by calling `on(value: <Proc>)` on it.
83
+
84
+ ```ruby
85
+ trackable.on(value: ->(v) { p v })
86
+
87
+ # same as
88
+ trackable.on do |val|
89
+ p val
90
+ end
91
+ ```
92
+
93
+ This way the `Trackable` will _push_ the values to our _consumer_ lambda/block.
94
+ So in this case it is pretty much the same as with the `Enumerator`. The
95
+ main difference is that our code is not _pulling_ the values from the
96
+ `Trackable`, instead, the `Trackable` is _pushing_ the values, when they are
97
+ ready, to our client code.
98
+
99
+ As with the `Enumerator`, which includes the `Enumerable` module, `Reacto::Trackable` has
100
+ a lot of handy functions (called operations - `map`, `select`, etc. - more on them later) we can chain to it.
101
+ A difference between `Trackable` and `Enumerator` is that we can track for errors and `close` notifications
102
+ too.
103
+
104
+ ```ruby
105
+ trackable.on(
106
+ error: ->(e) { p e.message }, value: ->(v) { p v }, close: ->() { p 'DONE' }
107
+ )
108
+ ```
109
+
110
+ Now if there is an error while receiving the values, it will be passed to
111
+ the error-handling lambda.
112
+ So we can react to incoming notifications and even errors. The `close`
113
+ notification is flagging that all the incoming data has arrived.
114
+
115
+ Let's sum it up - a `Reacto::Trackable` is much like an `Enumerator`, but
116
+ our consumer code is not _pulling_ the data from it, it is instead _tracking_
117
+ it for notifications. These notifications could be values, errors, or
118
+ `close` ones. They are _pushed_ to our consumer code when available.
119
+
120
+ ## Asynchronous programming
121
+
122
+ By default when we call `on` on a `Reacto::Trackable` instance, our program blocks
123
+ and waits for all the notifications to arrive until an error or `close`
124
+ notification is received. That's OK, but as said, values are received
125
+ when available, so in some cases it will be more efficient to do something else
126
+ while waiting for the values to come.
127
+ Enter `execute_on`. It, like all the other operations that can be called on
128
+ `Reacto::Trackable`, creates a new `Trackable` with source the caller.
129
+ The new one will execute all of its operations on the _Executor_ passed to the
130
+ `execute_on`. An _Executor_ is a service that manages threads.
131
+
132
+ ```ruby
133
+ trackable = trackable.execute_on(:background)
134
+ trackable.on(
135
+ error: ->(e) { p e.message }, value: ->(v) { p v }, close: ->() { p 'DONE' }
136
+ )
137
+
138
+ # The call to `on` won't block so we can have some code here, which will
139
+ # execute immediately after it. When the values arrive, they'll be printed.
140
+
141
+ ```
142
+
143
+ It's that easy to have code in the background. And what if we want to block
144
+ at some point?
145
+ First of all the `on` method returns a `Reacto::Subscription` instance
146
+ which we can use to `unsubscribe` from the `Reacto::Trackable` or do other
147
+ things. One of this things is to pass it to `Reacto::Trackable#await`:
148
+
149
+ ```ruby
150
+ trackable = trackable.execute_on(:background)
151
+ subscription = trackable.on(
152
+ error: ->(e) { p e.message }, value: ->(v) { p v }, close: ->() { p 'DONE' }
153
+ )
154
+
155
+ # Some code we want to be executed while waiting for values
156
+
157
+ trackable.await(subscription) # Block until an error or close notification arives
158
+ ```
159
+
160
+ That's how easy it is.
161
+
162
+ ## Operations
163
+
164
+ So we were just talking about the _code_ in the background, but what kind of
165
+ code can we attach to the `Reacto::Trackable`s exactly?
166
+ We can answer that by defining what an *operation* is. An *operation* is
167
+ called on a `Reacto::Trackable` instance and it always returns a new
168
+ `Reacto::Trackable` instance with source the caller.
169
+ The *operation* will change the incoming notifications,
170
+ when the tracking takes places. Let's look at some examples:
171
+
172
+ #### Map
173
+
174
+ The `map` operation is a simple transformation. It's the same as
175
+ the `Enumerable`'s `map` - transforms each of the values into something else
176
+ using the passed `block`'s return values'.
177
+
178
+ ```ruby
179
+ source = Reacto::Trackable.enumerable((1..5))
180
+
181
+ trackable = source.map { |v| v * v * v }
182
+ trackable.on { |val| p val } # Will print 1 8 27 64 125
183
+ ```
184
+
185
+ #### Select
186
+
187
+ The `select` operation filters incoming values, again similar to its
188
+ `Enumerable` counterpart.
189
+
190
+
191
+ ```ruby
192
+ source = Reacto::Trackable.enumerable((1..5))
193
+
194
+ trackable = source.select { |v| v % 2 == 0 }
195
+ trackable.on { |val| p val } # will print 2 4
196
+ ```
197
+
198
+ #### Inject
199
+
200
+ Of course there is the `inject` operation which gives us the opportunity
201
+ to combine the current incoming value with the previous one and emit that
202
+ as value.
203
+
204
+
205
+ ```ruby
206
+ source = Reacto::Trackable.enumerable((1..5))
207
+
208
+ trackable = source.inject { |prev, val| prev + val }
209
+ trackable.on { |val| p val } # will print 1 3(1+2) 6(3 + 3) 10(6 + 4) 15(10 + 5)
210
+ ```
211
+
212
+ Operation similar to `inject` are `diff`, which calls a given block for every
213
+ two consequetly emitted values and the `Reacto::Trackable` resulting from it,
214
+ emits this the block's return value. Another one is `each_with_object`, which
215
+ calls a given block for each value emitted by the source with an arbitrary
216
+ object given, and emits the initially given object.
217
+
218
+ #### FlatMap
219
+
220
+ Interesting operation is the `flat_map`. It accepts a block, which for
221
+ every call with a value must return an instance of `Reacto::Trackable`.
222
+ In the end the resulting `Reacto::Trackable` will emit all the values,
223
+ emitted by all of these returned by the block `Reacto::Trackable`s.
224
+
225
+ ```ruby
226
+ source = Reacto::Trackable.enumerable((1..5))
227
+
228
+ trackable = source.flat_map { |val| Reacto::Trackable.enumerable(val..6) }
229
+ trackable.on { |val| p val }
230
+ # will print 1 2 3 4 5 6 2 3 4 5 6 3 4 5 6 4 5 6 5 6
231
+ ```
232
+
233
+ This basically means that we can add operations to the inner `Reacto::Trackable`s too,
234
+ because all the available operations are producing `Reacto::Trackable` instances.
235
+
236
+ ## Links
237
+
238
+ TODO
data/lib/reacto.rb CHANGED
@@ -8,5 +8,75 @@ require 'reacto/shared_trackable'
8
8
  require 'reacto/labeled_trackable'
9
9
 
10
10
  module Reacto
11
+ module_function
11
12
 
13
+ def make(executor_param = nil, executor: executor, &block)
14
+ Trackable.make(executor_param, executor: executor, &block)
15
+ end
16
+
17
+ def never
18
+ Trackable.never
19
+ end
20
+
21
+ def close(executor: nil)
22
+ Trackable.close(executor: executor)
23
+ end
24
+
25
+ def error(err, executor: nil)
26
+ Trackable.error(err, executor: executor)
27
+ end
28
+
29
+ def value(value, executor: nil)
30
+ Trackable.value(value, executor: executor)
31
+ end
32
+
33
+ def enumerable(enumerable, executor: nil)
34
+ Trackable.enumerable(enumerable, executor: executor)
35
+ end
36
+
37
+ def later(secs, value, executor: :tasks)
38
+ Trackable.later(secs, value, executor: executor)
39
+ end
40
+
41
+ def interval(
42
+ interval, enumerator = Behaviours.integers_enumerator, executor: nil
43
+ )
44
+ Trackable.interval(interval, enumerator, executor: executor)
45
+ end
46
+
47
+ def repeat(array, int: 0.1, executor: nil)
48
+ Trackable.repeat(array, int: int, executor: executor)
49
+ end
50
+
51
+ def combine(*trackables, &block)
52
+ Trackable.combine(*trackables, &block)
53
+ end
54
+
55
+ def combine_last(*trackables, &block)
56
+ Trackable.combine_last(*trackables, &block)
57
+ end
58
+
59
+ def zip(*trackables, &block)
60
+ Trackable.zip(*trackables, &block)
61
+ end
62
+
63
+ def concat(*trackables)
64
+ Trackable.concat(*trackables)
65
+ end
66
+
67
+ def [](object)
68
+ if object.is_a?(Enumerable)
69
+ enumerable(object)
70
+ elsif object.is_a?(StandardError)
71
+ error(object)
72
+ elsif object == :close
73
+ close
74
+ elsif object == :never || object.nil?
75
+ never
76
+ else
77
+ value(object)
78
+ end
79
+ end
80
+
81
+ alias_method :combine_latest, :combine
12
82
  end
@@ -25,11 +25,26 @@ module Reacto
25
25
  end
26
26
  end
27
27
 
28
+ def enumerable(enumerable_value)
29
+ ->(tracker) do
30
+ begin
31
+ enumerable_value.each do |val|
32
+ break unless tracker.subscribed?
33
+ tracker.on_value(val)
34
+ end
35
+
36
+ tracker.on_close if tracker.subscribed?
37
+ rescue => error
38
+ tracker.on_error(error) if tracker.subscribed?
39
+ end
40
+ end
41
+ end
42
+
28
43
  def integers_enumerator
29
44
  Enumerator.new do |yielder|
30
45
  n = 0
31
46
  loop do
32
- yielder.yield n
47
+ yielder << n
33
48
  n = n + 1
34
49
  end
35
50
  end
@@ -46,5 +61,13 @@ module Reacto
46
61
  end
47
62
  end
48
63
  end
64
+
65
+ def constant(const)
66
+ -> (_val) { const }
67
+ end
68
+
69
+ def same_predicate(val)
70
+ -> (value) { val == value }
71
+ end
49
72
  end
50
73
  end
@@ -1,7 +1,10 @@
1
1
  module Reacto
2
2
  NOTHING = {}
3
- NO_ACTION = -> (*args) {}
3
+ NO_ACTION = -> (*_args) {}
4
+ IDENTITY_ACTION = -> (arg) { arg }
4
5
  DEFAULT_ON_ERROR = -> (e) { raise e }
5
6
  ID = -> (v) { v }
6
7
  NO_VALUE = {}
8
+ TRUE_PREDICATE = -> (_val) { true }
9
+ FALSE_PREDICATE = -> (_val) { false }
7
10
  end
@@ -4,28 +4,26 @@ require 'concurrent/executor/fixed_thread_pool'
4
4
 
5
5
  module Reacto
6
6
  module Executors
7
- class CurrentExecutor
8
- def post
9
-
10
- end
11
- end
12
-
13
7
  module_function
14
8
 
15
9
  def immediate
16
- Concurrent::ImmediateExecutor.new
10
+ @immediate ||= Concurrent::ImmediateExecutor.new
17
11
  end
18
12
 
19
13
  def current
20
- Concurrent::ImmediateExecutor.new
14
+ immediate
21
15
  end
22
16
 
23
17
  def io
24
- Concurrent::CachedThreadPool.new
18
+ @io ||= Concurrent::CachedThreadPool.new
25
19
  end
26
20
 
27
21
  def tasks
28
- Concurrent::FixedThreadPool.new(4) # Number of cores here?
22
+ @tasks ||= Concurrent::FixedThreadPool.new(4) # Number of cores here?
23
+ end
24
+
25
+ def new_thread
26
+ @new_thread ||= Concurrent::SimpleExecutorService.new
29
27
  end
30
28
  end
31
29
  end
@@ -4,10 +4,22 @@ module Reacto
4
4
  class LabeledTrackable < Trackable
5
5
  attr_reader :label
6
6
 
7
- def initialize(label, executor = nil, behaviour = NO_ACTION, &block)
8
- super(behaviour, executor, &block)
7
+ def initialize(label, executor = nil, &block)
8
+ super(executor, &block)
9
9
 
10
10
  @label = label
11
11
  end
12
+
13
+ def relabel
14
+ new_label = yield label
15
+
16
+ self.class.new(new_label, @executor, &@behaviour)
17
+ end
18
+
19
+ protected
20
+
21
+ def create_lifted(&block)
22
+ self.class.new(label, @executor, &block)
23
+ end
12
24
  end
13
25
  end
@@ -4,20 +4,41 @@ require 'reacto/operations/select'
4
4
  require 'reacto/operations/inject'
5
5
  require 'reacto/operations/diff'
6
6
  require 'reacto/operations/drop'
7
+ require 'reacto/operations/drop_while'
7
8
  require 'reacto/operations/drop_errors'
8
9
  require 'reacto/operations/take'
10
+ require 'reacto/operations/take_while'
9
11
  require 'reacto/operations/last'
10
12
  require 'reacto/operations/track_on'
11
13
  require 'reacto/operations/prepend'
14
+ require 'reacto/operations/append'
12
15
  require 'reacto/operations/concat'
13
16
  require 'reacto/operations/merge'
14
17
  require 'reacto/operations/buffer'
18
+ require 'reacto/operations/delay_each'
15
19
  require 'reacto/operations/uniq'
16
20
  require 'reacto/operations/flatten'
17
21
  require 'reacto/operations/throttle'
18
22
  require 'reacto/operations/flat_map'
19
23
  require 'reacto/operations/flat_map_latest'
20
- require 'reacto/operations/cache'
21
24
  require 'reacto/operations/depend_on'
22
- require 'reacto/operations/label'
25
+ require 'reacto/operations/group_by_label'
26
+ require 'reacto/operations/operation_on_labeled'
27
+ require 'reacto/operations/flatten_labeled'
28
+ require 'reacto/operations/split_labeled'
23
29
  require 'reacto/operations/act'
30
+ require 'reacto/operations/retry'
31
+ require 'reacto/operations/retry_when'
32
+ require 'reacto/operations/rescue_and_replace_error'
33
+ require 'reacto/operations/blocking_enumerable'
34
+ require 'reacto/operations/chunk'
35
+ require 'reacto/operations/chunk_while'
36
+ require 'reacto/operations/cycle'
37
+ require 'reacto/operations/each_collect'
38
+ require 'reacto/operations/each_with_object'
39
+ require 'reacto/operations/find_index'
40
+ require 'reacto/operations/include'
41
+ require 'reacto/operations/extremums'
42
+ require 'reacto/operations/partition'
43
+ require 'reacto/operations/slice'
44
+ require 'reacto/operations/slice_when'