parallel(pipeline)
[folly.git] / folly / gen / Base.h
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef FOLLY_GEN_BASE_H
18 #define FOLLY_GEN_BASE_H
19
20 #include <functional>
21 #include <memory>
22 #include <type_traits>
23 #include <utility>
24 #include <algorithm>
25 #include <random>
26 #include <vector>
27 #include <unordered_set>
28
29 #include "folly/Range.h"
30 #include "folly/Optional.h"
31 #include "folly/Conv.h"
32 #include "folly/gen/Core.h"
33
34 /**
35  * Generator-based Sequence Comprehensions in C++, akin to C#'s LINQ
36  * @author Tom Jackson <tjackson@fb.com>
37  *
38  * This library makes it possible to write declarative comprehensions for
39  * processing sequences of values efficiently in C++. The operators should be
40  * familiar to those with experience in functional programming, and the
41  * performance will be virtually identical to the equivalent, boilerplate C++
42  * implementations.
43  *
44  * Generator objects may be created from either an stl-like container (anything
45  * supporting begin() and end()), from sequences of values, or from another
46  * generator (see below). To create a generator that pulls values from a vector,
47  * for example, one could write:
48  *
49  *   vector<string> names { "Jack", "Jill", "Sara", "Tom" };
50  *   auto gen = from(names);
51  *
52  * Generators are composed by building new generators out of old ones through
53  * the use of operators. These are reminicent of shell pipelines, and afford
54  * similar composition. Lambda functions are used liberally to describe how to
55  * handle individual values:
56  *
57  *   auto lengths = gen
58  *                | mapped([](const fbstring& name) { return name.size(); });
59  *
60  * Generators are lazy; they don't actually perform any work until they need to.
61  * As an example, the 'lengths' generator (above) won't actually invoke the
62  * provided lambda until values are needed:
63  *
64  *   auto lengthVector = lengths | as<std::vector>();
65  *   auto totalLength = lengths | sum;
66  *
67  * 'auto' is useful in here because the actual types of the generators objects
68  * are usually complicated and implementation-sensitive.
69  *
70  * If a simpler type is desired (for returning, as an example), VirtualGen<T>
71  * may be used to wrap the generator in a polymorphic wrapper:
72  *
73  *  VirtualGen<float> powersOfE() {
74  *    return seq(1) | mapped(&expf);
75  *  }
76  *
77  * To learn more about this library, including the use of infinite generators,
78  * see the examples in the comments, or the docs (coming soon).
79 */
80
81 namespace folly { namespace gen {
82
83 class EmptySequence : public std::exception {
84 public:
85   virtual const char* what() const noexcept {
86     return "This operation cannot be called on an empty sequence";
87   }
88 };
89
90 class Less {
91 public:
92   template<class First,
93            class Second>
94   auto operator()(const First& first, const Second& second) const ->
95   decltype(first < second) {
96     return first < second;
97   }
98 };
99
100 class Greater {
101 public:
102   template<class First,
103            class Second>
104   auto operator()(const First& first, const Second& second) const ->
105   decltype(first > second) {
106     return first > second;
107   }
108 };
109
110 template<int n>
111 class Get {
112 public:
113   template<class Value>
114   auto operator()(Value&& value) const ->
115   decltype(std::get<n>(std::forward<Value>(value))) {
116     return std::get<n>(std::forward<Value>(value));
117   }
118 };
119
120 template<class Class,
121          class Result>
122 class MemberFunction {
123  public:
124   typedef Result (Class::*MemberPtr)();
125  private:
126   MemberPtr member_;
127  public:
128   explicit MemberFunction(MemberPtr member)
129     : member_(member)
130   {}
131
132   Result operator()(Class&& x) const {
133     return (x.*member_)();
134   }
135
136   Result operator()(Class& x) const {
137     return (x.*member_)();
138   }
139 };
140
141 template<class Class,
142          class Result>
143 class ConstMemberFunction{
144  public:
145   typedef Result (Class::*MemberPtr)() const;
146  private:
147   MemberPtr member_;
148  public:
149   explicit ConstMemberFunction(MemberPtr member)
150     : member_(member)
151   {}
152
153   Result operator()(const Class& x) const {
154     return (x.*member_)();
155   }
156 };
157
158 template<class Class,
159          class FieldType>
160 class Field {
161  public:
162   typedef FieldType (Class::*FieldPtr);
163  private:
164   FieldPtr field_;
165  public:
166   explicit Field(FieldPtr field)
167     : field_(field)
168   {}
169
170   const FieldType& operator()(const Class& x) const {
171     return x.*field_;
172   }
173
174   FieldType& operator()(Class& x) const {
175     return x.*field_;
176   }
177
178   FieldType&& operator()(Class&& x) const {
179     return std::move(x.*field_);
180   }
181 };
182
183 class Move {
184 public:
185   template<class Value>
186   auto operator()(Value&& value) const ->
187   decltype(std::move(std::forward<Value>(value))) {
188     return std::move(std::forward<Value>(value));
189   }
190 };
191
192 class Identity {
193 public:
194   template<class Value>
195   auto operator()(Value&& value) const ->
196   decltype(std::forward<Value>(value)) {
197     return std::forward<Value>(value);
198   }
199 };
200
201 template <class Dest>
202 class Cast {
203  public:
204   template <class Value>
205   Dest operator()(Value&& value) const {
206     return Dest(std::forward<Value>(value));
207   }
208 };
209
210 template <class Dest>
211 class To {
212  public:
213   template <class Value>
214   Dest operator()(Value&& value) const {
215     return ::folly::to<Dest>(std::forward<Value>(value));
216   }
217 };
218
219 // Specialization to allow String->StringPiece conversion
220 template <>
221 class To<StringPiece> {
222  public:
223   StringPiece operator()(StringPiece src) const {
224     return src;
225   }
226 };
227
228 namespace detail {
229
230 template<class Self>
231 struct FBounded;
232
233 /*
234  * Type Traits
235  */
236 template<class Container>
237 struct ValueTypeOfRange {
238  private:
239   static Container container_;
240  public:
241   typedef decltype(*std::begin(container_))
242     RefType;
243   typedef typename std::decay<decltype(*std::begin(container_))>::type
244     StorageType;
245 };
246
247
248 /*
249  * Sources
250  */
251 template<class Container,
252          class Value = typename ValueTypeOfRange<Container>::RefType>
253 class ReferencedSource;
254
255 template<class Value,
256          class Container = std::vector<typename std::decay<Value>::type>>
257 class CopiedSource;
258
259 template<class Value, bool endless = false, bool endInclusive = false>
260 class Sequence;
261
262 template<class Value, class Source>
263 class Yield;
264
265 template<class Value>
266 class Empty;
267
268 template<class Value>
269 class Just;
270
271 /*
272  * Operators
273  */
274 template<class Predicate>
275 class Map;
276
277 template<class Predicate>
278 class Filter;
279
280 template<class Predicate>
281 class Until;
282
283 class Take;
284
285 template<class Rand>
286 class Sample;
287
288 class Skip;
289
290 template<class Selector, class Comparer = Less>
291 class Order;
292
293 template<class Selector>
294 class Distinct;
295
296 template<class Operators>
297 class Composer;
298
299 template<class Expected>
300 class TypeAssertion;
301
302 class Concat;
303
304 class RangeConcat;
305
306 class Cycle;
307
308 class Batch;
309
310 class Dereference;
311
312 /*
313  * Sinks
314  */
315 template<class Seed,
316          class Fold>
317 class FoldLeft;
318
319 class First;
320
321 class Any;
322
323 template<class Predicate>
324 class All;
325
326 template<class Reducer>
327 class Reduce;
328
329 class Sum;
330
331 template<class Selector,
332          class Comparer>
333 class Min;
334
335 template<class Container>
336 class Collect;
337
338 template<template<class, class> class Collection = std::vector,
339          template<class> class Allocator = std::allocator>
340 class CollectTemplate;
341
342 template<class Collection>
343 class Append;
344
345 template<class Value>
346 struct GeneratorBuilder;
347
348 template<class Needle>
349 class Contains;
350
351 template<class Exception,
352          class ErrorHandler>
353 class GuardImpl;
354
355 }
356
357 /**
358  * Polymorphic wrapper
359  **/
360 template<class Value>
361 class VirtualGen;
362
363 /*
364  * Source Factories
365  */
366 template<class Container,
367          class From = detail::ReferencedSource<const Container>>
368 From fromConst(const Container& source) {
369   return From(&source);
370 }
371
372 template<class Container,
373          class From = detail::ReferencedSource<Container>>
374 From from(Container& source) {
375   return From(&source);
376 }
377
378 template<class Container,
379          class Value =
380            typename detail::ValueTypeOfRange<Container>::StorageType,
381          class CopyOf = detail::CopiedSource<Value>>
382 CopyOf fromCopy(Container&& source) {
383   return CopyOf(std::forward<Container>(source));
384 }
385
386 template<class Value,
387          class From = detail::CopiedSource<Value>>
388 From from(std::initializer_list<Value> source) {
389   return From(source);
390 }
391
392 template<class Container,
393          class From = detail::CopiedSource<typename Container::value_type,
394                                            Container>>
395 From from(Container&& source) {
396   return From(std::move(source));
397 }
398
399 template<class Value, class Gen = detail::Sequence<Value, false, false>>
400 Gen range(Value begin, Value end) {
401   return Gen(begin, end);
402 }
403
404 template<class Value,
405          class Gen = detail::Sequence<Value, false, true>>
406 Gen seq(Value first, Value last) {
407   return Gen(first, last);
408 }
409
410 template<class Value,
411          class Gen = detail::Sequence<Value, true>>
412 Gen seq(Value begin) {
413   return Gen(begin);
414 }
415
416 template<class Value,
417          class Source,
418          class Yield = detail::Yield<Value, Source>>
419 Yield generator(Source&& source) {
420   return Yield(std::forward<Source>(source));
421 }
422
423 /*
424  * Create inline generator, used like:
425  *
426  *  auto gen = GENERATOR(int) { yield(1); yield(2); };
427  */
428 #define GENERATOR(TYPE)                            \
429   ::folly::gen::detail::GeneratorBuilder<TYPE>() + \
430    [=](const std::function<void(TYPE)>& yield)
431
432 /*
433  * empty() - for producing empty sequences.
434  */
435 template<class Value>
436 detail::Empty<Value> empty() {
437   return {};
438 }
439
440 template<class Value>
441 detail::Just<Value> just(Value value) {
442   return detail::Just<Value>(std::move(value));
443 }
444
445 /*
446  * Operator Factories
447  */
448 template<class Predicate,
449          class Map = detail::Map<Predicate>>
450 Map mapped(Predicate pred = Predicate()) {
451   return Map(std::move(pred));
452 }
453
454 template<class Predicate,
455          class Map = detail::Map<Predicate>>
456 Map map(Predicate pred = Predicate()) {
457   return Map(std::move(pred));
458 }
459
460 /**
461  * mapOp - Given a generator of generators, maps the application of the given
462  * operator on to each inner gen. Especially useful in aggregating nested data
463  * structures:
464  *
465  *   chunked(samples, 256)
466  *     | mapOp(filter(sampleTest) | count)
467  *     | sum;
468  */
469 template<class Operator,
470          class Map = detail::Map<detail::Composer<Operator>>>
471 Map mapOp(Operator op) {
472   return Map(detail::Composer<Operator>(std::move(op)));
473 }
474
475 /*
476  * member(...) - For extracting a member from each value.
477  *
478  *  vector<string> strings = ...;
479  *  auto sizes = from(strings) | member(&string::size);
480  *
481  * If a member is const overridden (like 'front()'), pass template parameter
482  * 'Const' to select the const version, or 'Mutable' to select the non-const
483  * version:
484  *
485  *  auto heads = from(strings) | member<Const>(&string::front);
486  */
487 enum MemberType {
488   Const,
489   Mutable
490 };
491
492 template<MemberType Constness = Const,
493          class Class,
494          class Return,
495          class Mem = ConstMemberFunction<Class, Return>,
496          class Map = detail::Map<Mem>>
497 typename std::enable_if<Constness == Const, Map>::type
498 member(Return (Class::*member)() const) {
499   return Map(Mem(member));
500 }
501
502 template<MemberType Constness = Mutable,
503          class Class,
504          class Return,
505          class Mem = MemberFunction<Class, Return>,
506          class Map = detail::Map<Mem>>
507 typename std::enable_if<Constness == Mutable, Map>::type
508 member(Return (Class::*member)()) {
509   return Map(Mem(member));
510 }
511
512 /*
513  * field(...) - For extracting a field from each value.
514  *
515  *  vector<Item> items = ...;
516  *  auto names = from(items) | field(&Item::name);
517  *
518  * Note that if the values of the generator are rvalues, any non-reference
519  * fields will be rvalues as well. As an example, the code below does not copy
520  * any strings, only moves them:
521  *
522  *  auto namesVector = from(items)
523  *                   | move
524  *                   | field(&Item::name)
525  *                   | as<vector>();
526  */
527 template<class Class,
528          class FieldType,
529          class Field = Field<Class, FieldType>,
530          class Map = detail::Map<Field>>
531 Map field(FieldType Class::*field) {
532   return Map(Field(field));
533 }
534
535 template<class Predicate,
536          class Filter = detail::Filter<Predicate>>
537 Filter filter(Predicate pred = Predicate()) {
538   return Filter(std::move(pred));
539 }
540
541 template<class Predicate,
542          class All = detail::All<Predicate>>
543 All all(Predicate pred = Predicate()) {
544   return All(std::move(pred));
545 }
546
547 template<class Predicate,
548          class Until = detail::Until<Predicate>>
549 Until until(Predicate pred = Predicate()) {
550   return Until(std::move(pred));
551 }
552
553 template<class Selector,
554          class Comparer = Less,
555          class Order = detail::Order<Selector, Comparer>>
556 Order orderBy(Selector selector = Identity(),
557               Comparer comparer = Comparer()) {
558   return Order(std::move(selector),
559                std::move(comparer));
560 }
561
562 template<class Selector,
563          class Order = detail::Order<Selector, Greater>>
564 Order orderByDescending(Selector selector = Identity()) {
565   return Order(std::move(selector));
566 }
567
568 template<class Selector,
569          class Distinct = detail::Distinct<Selector>>
570 Distinct distinctBy(Selector selector = Identity()) {
571   return Distinct(std::move(selector));
572 }
573
574 template<int n,
575          class Get = detail::Map<Get<n>>>
576 Get get() {
577   return Get();
578 }
579
580 // construct Dest from each value
581 template <class Dest,
582           class Cast = detail::Map<Cast<Dest>>>
583 Cast eachAs() {
584   return Cast();
585 }
586
587 // call folly::to on each value
588 template <class Dest,
589           class To = detail::Map<To<Dest>>>
590 To eachTo() {
591   return To();
592 }
593
594 template<class Value>
595 detail::TypeAssertion<Value> assert_type() {
596   return {};
597 }
598
599 /*
600  * Sink Factories
601  */
602 template<class Seed,
603          class Fold,
604          class FoldLeft = detail::FoldLeft<Seed, Fold>>
605 FoldLeft foldl(Seed seed = Seed(),
606                Fold fold = Fold()) {
607   return FoldLeft(std::move(seed),
608                   std::move(fold));
609 }
610
611 template<class Reducer,
612          class Reduce = detail::Reduce<Reducer>>
613 Reduce reduce(Reducer reducer = Reducer()) {
614   return Reduce(std::move(reducer));
615 }
616
617 template<class Selector = Identity,
618          class Min = detail::Min<Selector, Less>>
619 Min minBy(Selector selector = Selector()) {
620   return Min(std::move(selector));
621 }
622
623 template<class Selector,
624          class MaxBy = detail::Min<Selector, Greater>>
625 MaxBy maxBy(Selector selector = Selector()) {
626   return MaxBy(std::move(selector));
627 }
628
629 template<class Collection,
630          class Collect = detail::Collect<Collection>>
631 Collect as() {
632   return Collect();
633 }
634
635 template<template<class, class> class Container = std::vector,
636          template<class> class Allocator = std::allocator,
637          class Collect = detail::CollectTemplate<Container, Allocator>>
638 Collect as() {
639   return Collect();
640 }
641
642 template<class Collection,
643          class Append = detail::Append<Collection>>
644 Append appendTo(Collection& collection) {
645   return Append(&collection);
646 }
647
648 template<class Needle,
649          class Contains = detail::Contains<typename std::decay<Needle>::type>>
650 Contains contains(Needle&& needle) {
651   return Contains(std::forward<Needle>(needle));
652 }
653
654 template<class Exception,
655          class ErrorHandler,
656          class GuardImpl =
657            detail::GuardImpl<
658              Exception,
659              typename std::decay<ErrorHandler>::type>>
660 GuardImpl guard(ErrorHandler&& handler) {
661   return GuardImpl(std::forward<ErrorHandler>(handler));
662 }
663
664 }} // folly::gen
665
666 #include "folly/gen/Base-inl.h"
667
668 #endif // FOLLY_GEN_BASE_H