{"id":22614367,"url":"https://github.com/cwahn/efp","last_synced_at":"2025-08-22T05:31:18.544Z","repository":{"id":178996818,"uuid":"662683651","full_name":"cwahn/efp","owner":"cwahn","description":"Expressive High-Performance Eager Functional Programming Library for C++ 11","archived":false,"fork":false,"pushed_at":"2024-11-07T13:59:15.000Z","size":982,"stargazers_count":48,"open_issues_count":1,"forks_count":1,"subscribers_count":6,"default_branch":"main","last_synced_at":"2024-11-07T14:35:21.452Z","etag":null,"topics":["adt","cpp","cpp11","functional-programming","higher-order-component","sum-types"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cwahn.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":"CODEOWNERs","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-05T16:54:20.000Z","updated_at":"2024-09-17T06:19:04.000Z","dependencies_parsed_at":"2024-01-30T03:29:26.079Z","dependency_job_id":"132bd993-b9bb-499e-8f4e-585ec4ae1fc6","html_url":"https://github.com/cwahn/efp","commit_stats":null,"previous_names":["cwahn/embedded-eager-functional-programming"],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cwahn%2Fefp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cwahn%2Fefp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cwahn%2Fefp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cwahn%2Fefp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cwahn","download_url":"https://codeload.github.com/cwahn/efp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228771097,"owners_count":17969911,"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":["adt","cpp","cpp11","functional-programming","higher-order-component","sum-types"],"created_at":"2024-12-08T18:09:32.162Z","updated_at":"2024-12-08T18:09:32.634Z","avatar_url":"https://github.com/cwahn.png","language":"C++","readme":"# EFP\n\n**\"Expressive High-Performance Eager Functional Programming Library for C++\"**\n\nThis is a header-only library for zero-cost functional programming in C++. It is highly influenced by the philosophy and style of Haskell and Rust, providing primitives leveraging the safety and expressive power of functional programming.\n\nTwo pillars of this library are the `Sequence` trait and the `Enum` container. `Sequence` traits effectively incarnate the concise sequential data manipulation of FP. `Enum` container is a disjoint union type like `std::variant` but based on C++ 11, and comes with Rust-like pattern matching. \n\nSupport freestanding(no-STL) C++ with some limitations.\n\n## Features\n\n### Sequence Trait\n\nGeneralization of contiguous sequential containers\n\nEFP offers no-STL contiguous sequence types and immutable view types implementing the Sequence trait: `Array`, `ArrVec`, `Vector`, `ArrayView`, `ArrVecView`, and `VectorView`\n\nSTL containers like `std::vector`, `std::array`, `std::string` also implement the `Sequence` trait. Therefore they could be used whenever sequence type is expected.\n\nAlso, the trait is not 'sealed'. Therefore one could implement `Sequence` trait for external types as well.\n\n#### Higher Order Functions\nEFP offers higher-order functions including   \n\n- Composition and Utility Functions: `compose`, `execute_pack`\n- Element Access and Manipulation: `head`, `last`, `tail`, `init`\n- Mapping Functions: `map`, `map_with_index`, `cartesian_map`\n- Folding Functions: `foldl`, `foldr`\n- Filtering Functions: `filter`, `take_while`, `drop_while`\n- Iteration Functions: `for_each`, `for_each_mut`, `for_each_with_index`, `for_each_with_index_mut`, `cartesian_for_each`, `cartesian_for_each_mut`, `for_index`, `cartesian_for_index`\n- Sequence Operations: `append`, `slice`, `slice_unsafe`, `take`, `take_unsafe`, `drop`, `drop_unsafe`\n- Element Search and Indexing: `elem`, `elem_index`, `elem_indices`, `find`, `find_index`, `find_indices`\n\nand many more.\n\n#### Automatic Allocation Avoidance\nHOFs of EFP often expect arguments implementing the `Sequence` trait and return another `Sequence`. By taking advantage of the type-level function, EFP automatically determines the resulting type in a manner that minimizes allocation in compile-time. The adequate type will be determined based on whether the capacity and length of the result are known in compile time from argument types.\n\nSequence-returning functions will return either `Array`, `ArrVec`, or `Vector`.\n\n- Static capacity \u0026\u0026 static length\n  - Array (analog of `std::array`)\n- Static capacity \u0026\u0026 dynamic length\n  - ArrVec (fixed capacity, no-allocation, on-stack variant of `std::vector`)\n- Dynamic capacity\n  - Vector (analog of `std::vector`)\n\n#### String and formatting\nJust like in Haskell, `String` is `Vector\u003cchar\u003e` in EFP (with minor difference on template argument). This enables string data manipulation with the same HOF used for all the other sequencial types. \n\nEFP also supports powerful formatting (and printing) features based on [fmtlib/fmt](https://github.com/fmtlib/fmt).\n\n### Sum Type with Pattern Matching\n\nEFP offers `Enum`, which is a sum type(or disjoint union type) similar to `std::variant` with rust-style pattern matching. \n\n- Exhaustive: Non-exhaustive branches will fail to be compiled.\n- Performance: Compiles to switch-case statement on the runtime tag. \n- Coherent: The matching rule is the same as that of the overloaded function.\n  \nOne drawback of `Enum` is memory usage. Like all the other tagged-union base implementations, `Enum` requires extra space to store the runtime tag of the stored variant. The tag itself is only 1 byte (hence supports 256 variants at maximum for now), but because of the memory alignment, the size of the resultant `Enum` tends to be larger than the size of the largest variant.\n\nEFP provides `Maybe\u003cA\u003e` which is inheriting `Enum\u003cNothing, A\u003e`. \n\n## Examples\n### General\n```cpp\n#include \u003ciostream\u003e\n#include \"efp.hpp\"\n\nusing namespace efp;\n\nconstexpr int n = 10;\n\nint main() {\n    const auto negate = [](int x) { return -x; };\n\n    const auto is_even = [](int x) { return x % 2 == 0; };\n\n    // Create a statically sized sequence, which is efp::Array\u003cint, n\u003e with identity function\n    const auto as = from_function(Int\u003cn\u003e {}, id\u003cint\u003e);\n    // Function composition\n    const auto minus_square = compose(negate, square\u003cint\u003e);\n    const auto bs = map(minus_square, as);\n    const auto cs = filter(is_even, bs);\n\n    println(\"Result is: {}\", cs);  // Result is: 0 -4 -16 -36 -64\n\n    const auto cout = [](int x) { std::cout \u003c\u003c x \u003c\u003c \" \"; };\n    for_each(cout, cs);  // 0 -4 -16 -36 -64\n\n    return 0;\n}\n```\n\n### Enum and Maybe with Pattern Matching\n```cpp\nconst Enum\u003cbool, int, double\u003e x = 2;  // Example with int\n\nconst int y = x.match(\n    [](int x) { return x * 2; },  // Specific branch for int\n    []() { return -1; }           // Wildcard branch\n);\nCHECK(y == 4);\n\n// Maybe\u003cA\u003e is a specialization of Enum\u003cNothing, A\u003e\nconst Maybe\u003cint\u003e maybe_42 = 42;\nconst Maybe\u003cint\u003e no_value = nothing;\n\n// Using value() and isEmpty() for direct value access and checking\nCHECK(maybe_42.value() == 42);\nCHECK(no_value.is_nothing() == true);\n\nconst int result = maybe_42.match(\n    [](int x) { return x; },  // Executes if there's a value\n    []() { return 0; }        // Executes if empty (wildcard)\n);\nCHECK(result == 42);\n```\n\n### String and Formatting\n```cpp\nconst String name_0 = \"Lighthouse\";\nconst String name_1 = \"Tinker Bell\";\n\nprintln(\"{}\", format(\"{} loves {}.\", name_0, name_1));\n``` \n\n### File IO\n```c++\nauto file = File::open(\"test\", \"w+\").move();\n\nfile.write(\"Hello, world!\\nThis is a test file.\\nEnd of test.\");\nfile.close();\n```\n\n## Benchmarks\nWIP\n\n## Testing\n\nEFP undergoes extensive testing with Catch2, leveraging pedantic warnings and Address Sanitizer to guarantee superior code quality and reliability.\n\n### Compatibility\n- **Compilers:** Clang 15, GCC 13\n- **C++ Standards:** C++11, C++14, C++17, C++20, C++23\n\n### Continuous Integration\nWe are in the process of setting up CI to automate testing and ensure consistent quality.\n\n### Test Suite Results\nOur comprehensive tests affirm EFP's robustness:\n\n```\n===============================================================================\nAll tests passed (1055 assertions in 107 test cases)\n```\n\n## Requirements\n\n- Requires C++ 11 or later.\n- Also supporte freestanding env. with some limitations.\n\n## Acknowledgement\n- Formatting\n  - The formatting functionality of EFP is based on the header-only version of the excellent [fmtlib/fmt](https://github.com/fmtlib/fmt).\n  - There have been modifications to the internal implementation \n    - Now internal implementation is based on `efp::BasicString`.\n    - APIs based on `efp::String`.\n  \n  \n## License\n\nDrafting of this library is started in July of 2023 by Ahn, Chanwoo for an embedded project. \n\nThis library is open-source under The MIT Liscence.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcwahn%2Fefp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcwahn%2Fefp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcwahn%2Fefp/lists"}