{"id":27057860,"url":"https://github.com/mrange/cppstreams","last_synced_at":"2025-04-05T11:33:46.771Z","repository":{"id":33690065,"uuid":"37342855","full_name":"mrange/CppStreams","owner":"mrange","description":"CppStreams is a data pipeline library for C++","archived":false,"fork":false,"pushed_at":"2015-08-01T12:53:55.000Z","size":348,"stargazers_count":14,"open_issues_count":0,"forks_count":2,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-02T02:09:04.930Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mrange.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-06-12T20:24:55.000Z","updated_at":"2024-02-08T10:34:10.000Z","dependencies_parsed_at":"2022-09-13T17:22:45.842Z","dependency_job_id":null,"html_url":"https://github.com/mrange/CppStreams","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrange%2FCppStreams","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrange%2FCppStreams/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrange%2FCppStreams/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrange%2FCppStreams/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mrange","download_url":"https://codeload.github.com/mrange/CppStreams/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247332057,"owners_count":20921849,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-05T11:33:41.349Z","updated_at":"2025-04-05T11:33:46.759Z","avatar_url":"https://github.com/mrange.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CppStreams\n\nCppStreams is a data pipeline library for C++14.\n\nExample:\n\n```c++\nusing namespace cpp_streams;\n\nstd::vector\u003cint\u003e ints {3,1,4,1,5,9,2,6,5,4};\n\n// Produce a sum of even ints (+1)\nauto sum =\n      from (ints)\n  \u003e\u003e  filter ([] (auto \u0026\u0026 v) {return v % 2 == 0;})  // Keep only even numbers\n  \u003e\u003e  map ([] (auto \u0026\u0026 v) {return v + 1;})          // +1\n  \u003e\u003e  to_sum                                        // Compute sum\n  ;\n\nstd::cout \u003c\u003c \"SUM: \" \u003c\u003c sum \u003c\u003c std::endl;\n```\n\n## Verified compilers\n1. Visual Studio 2015\n2. G++ 4.9.2\n3. Clang++ 3.6.0\n\n## Motivation\n\nIn functional programming languages, such as Haskell \u0026 SML, programmers have been working with\ndata pipelines for 30+ years.\n\n\"Recently\" this has become available to mainstream programmers in\nlanguages such as C# (2008, LINQ) and Java (2014, Streams) as these languages has begun adopting\nmore functional constructs.\n\nWith C++11 C++ got lambda expressions which is crucial  in order\nto implement data pipelines. Several attempts have been made to implement data pipelines among\nothers [cpplinq](https://cpplinq.codeplex.com/) that I begun working on during summer 2012.\n\nThe motivation for CppStreams are:\n\n1. Use push instead of pull as this seems to lead to more efficient pipelines.\n2. Support of update of source container (cpplinq can't do this)\n3. Use C++14 in order to make the library code more succinct and easier to extend.\n4. Use functional naming conventions over C# LINQ naming conventions.\n5. Having a bit of fun\n\n## Inspiration\n\n1. C# LINQ got me interested in data pipelines\n2. [F#](https://github.com/Microsoft/visualfsharp) made me\n   to rediscover FP\n3. [nessos/Streams](https://github.com/nessos/Streams) is a data pipeline for F#/C# that relies on push\n4. Even though I authored [cpplinq](https://cpplinq.codeplex.com/) it's still an inspiration for\n   CppStreams in terms of goals and learning on what can be improved\n\n## Status\n\n### Source operators\n\n* - Currently doesn't work on VS2015 RC\n\n| Prio | Status  | Source operator         | Comment                                            |\n|-----:| --------|-------------------------|----------------------------------------------------|\n|      | Done    | from                    | Creates a source from a STL container              |\n|      | Done    | from_iterators          | Creates a source from a pair of iterators          |\n|      | Done    | from_array              | Creates a source from a C-style array              |\n|      | Done    | from_repeat             | Creates an source from a value and repeat count    |\n|      | Done    | from_singleton          | Creates an source from a value                     |\n|      | Done    | from_empty              | Creates an empty source                            |\n|      | Done    | from_range*             | Creates a source from a range                      |\n|    2 | Planned | from_unfold             | Creates an source from an unfold function          |\n|    2 | Planned | from_generator          | Creates an source from a generator function        |\n\n### Pipe operators\n\n| Prio | Status  | Pipe operator           | Comment                                            |\n|-----:| --------|-------------------------|----------------------------------------------------|\n|      | Done    | filter                  | Filter elements in pipeline using filter function  |\n|      | Done    | map                     | Maps elements in pipeline using map function       |\n|      | Done    | reverse*                | Reverses elements in pipeline                      |\n|      | Done    | append                  | Appends two pipelines                              |\n|      | Done    | skip_while              | Skips while func is true for elements in pipeline  |\n|      | Done    | take_while              | Takes while func is true for elements in pipeline  |\n|      | Done    | mapi                    | Maps elements in pipeline using mapi function      |\n|      | Done    | collect                 | Collects sub elements in pipeline                  |\n|      | Done    | skip                    | Skips n elements in pipeline                       |\n|      | Done    | take                    | Takes n elements in pipeline                       |\n|      | Done    | sort*                   | Orders elements in pipeline using order function   |\n|      | Done    | sort_by*                | Orders elements in pipeline using order function   |\n|    1 | Planned | order_by                | Orders elements in pipeline using order function   |\n|    1 | Planned | then_by                 | Orders elements in pipeline using order function   |\n|    1 | Planned | concat                  | Concats a pipeline of pipelines                    |\n|    2 | Planned | choose                  | Chooses elements in pipeline                       |\n|    2 | Planned | distinct_by             | Unique elements in pipeline using select function  |\n|    2 | Planned | partition               | Partitions elements in pipeline in two heaps       |\n|    2 | Planned | reduce                  | Reduces elements in pipeline using reduce function |\n|    2 | Planned | union_with              | Union of two pipelines                             |\n|    2 | Planned | intersect_with          | Intersection of two pipelines                      |\n|    2 | Planned | expect_with             | Disjunction of two pipelines                       |\n|    2 | Planned | windowed                | Splits elements in pipeline in chunks              |\n|    2 | Planned | compare_with            | Compares two pipelines                             |\n|    2 | Planned | pairwise                | Makes pair of elements in pipeline                 |\n|    2 | Planned | permute                 | Permutes elements in pipeline using permutes func  |\n|    2 | Planned | join_with               | Joins two pipelines                                |\n\n### Sink operators\n\n| Prio | Status  | Sink operator           | Comment                                            |\n|-----:| --------|-------------------------|----------------------------------------------------|\n|      | Done    | to_first_or_default     | Returns the first element of pipeline or default   |\n|      | Done    | to_last_or_default      | Returns the last element of pipeline or default    |\n|      | Done    | to_sum                  | Returns sum of elements in pipeline                |\n|      | Done    | to_vector               | Returns vector of elements in pipeline             |\n|      | Done    | to_iter                 | Applies iteration function to elements in pipeline |\n|      | Done    | to_fold                 | Applies fold function to elements in pipeline      |\n|      | Done    | to_any                  | True if pipeline has any element matching predicate|\n|      | Done    | to_all                  | True if all pipeline element matches predicate     |\n|      | Done    | to_length               | Returns length of elements in pipeline             |\n|      | Done    | to_set                  | Returns set of elements in pipeline                |\n|      | Done    | to_map*                 | Returns map of elements in pipeline                |\n|      | Done    | to_max                  | Returns max of elements in pipeline                |\n|      | Done    | to_min                  | Returns min of elements in pipeline                |\n|    2 | Planned | to_average              | Returns average of elements in pipeline            |\n|    2 | Planned | to_first                | Returns the first element of pipeline or empty     |\n|    2 | Planned | to_split_at             | Splits a pipeline at index n                       |\n|    2 | Planend | to_last                 | Returns the last element of pipeline or empty      |\n|    2 | Planned | to_lookup               | Returns lookup of elements in pipeline             |\n|    2 | Planned | to_scan                 | Applies scan function to elements in pipeline      |\n|    2 | Planned | to_split_into           | Splits a pipeline into at most n chunks            |\n\n# TODO\n\nNEXT: 011\n\n1. 010 - VS2015: Find work-around for busted pipes\n1. 006 - performance: Add performance tests\n1. 007 - coverage: Add code coverage tests\n1. 001 - general: Capture by RValue reference as implied here: [capture-by-universal-reference](http://stackoverflow.com/questions/21238463/capture-by-universal-reference)\n1. 002 - iteration_sink: Check return type, if void return false\n1. 008 - general: Use static_assert to check argument types\n1. 009 - general: Use std::forward in API functions\n1. 003 - from: Should capture the container by value if RValue reference\n1. 004 - test: Figure out how to test negative type test cases (these will trigger compilation errors).\n1. 005 - general: Not happy with the requirement to capture this in lambdas, find alternative\n\n## Done\n\n1. 000 - Complete status of operators\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrange%2Fcppstreams","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmrange%2Fcppstreams","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrange%2Fcppstreams/lists"}