Git Product home page Git Product logo

functional_vector's Introduction

CMake Build Matrix GitHub license

Say hello to functional C++ vectors

A wrapper for C++ std::vector geared towards functional programming and fluent APIs. The primary focus is readability at the call site (not performance) and eliminating manual management of vector indices. This is heavily influenced and inspired by C# and Swift.

Compilation (Cmake)

Dependencies

  • CMake >= 3.14

Minimum C++ version

  • C++11

An out-of-source build strategy is used. All following examples assume an output build folder named build. If no additional argument is passed to CMake, C++11 is used. Otherwise, you can pass -DCMAKE_CXX_STANDARD=17 and it will use C++17 for example.

macOS (Xcode)

cd functional_vector
cmake -S . -B build -G Xcode

Then open the generated functional_vector.xcodeproj in the build folder.

macOS (Makefiles/clang)

cd functional_vector
cmake -S . -B build
cmake --build build
build/tests/unit_tests

macOS (Makefiles/g++)

Assuming you have installed Homebrew, then you can use the gcc and g++ compilers by doing the following (this example uses version gcc 11)

cd functional_vector
cmake \
    -S . \
    -B build \
    -DCMAKE_C_COMPILER=/opt/homebrew/Cellar/gcc/11.2.0/bin/gcc-11 \
    -DCMAKE_CXX_COMPILER=/opt/homebrew/Cellar/gcc/11.2.0/bin/g++-11
cmake --build build
build/tests/unit_tests

Linux (Makefiles)

cd functional_vector
cmake -S . -B build
cmake --build build
build/tests/unit_tests

Windows (Visual Studio)

cd functional_vector
cmake -S . -B build

Then open the generated functional_vector.sln in the build folder.

Usage

zip, map, filter, sort

#include "functional_vector.h" // instead of <vector>

struct person {
    person(int age, std::string name)
    : age(age), name(std::move(name))
    {}
    int age;
    std::string name;
};

// ...

// the employees' ages
const functional_vector<int> ages({32, 45, 37, 23});

// the employees' names
const functional_vector<std::string> names({"Jake", "Anna", "Kate", "Bob"});

const auto employees_below_40 = ages
    // zip two vectors for simultaneous processing
    .zip(names)

    // apply the functional map algorithm (transform from one type to another)
    .map<person>([](const auto& pair) {                     
        return person(pair.first, pair.second);
    })
    
    // filter the elements using a local function (lambda)
    .filter([](const auto& person) {
        return person.age < 40;
    })
    
    // sort according to custom predicate
    .sort([](const auto& person1, const auto& person2) {
        return person1.age < person2.age;
    });

/*
 prints the following:
 Bob is 23 years old.
 Jake is 32 years old.
 Kate is 37 years old.
 */
employees_below_40.for_each([](const auto& person) {
    std::cout << person.name << " is " << person.age << " years old." << std::endl;
});

index search

#include "functional_vector.h" // instead of <vector>

const functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1});

const auto first_index_of_one = numbers.find_first_index(1);
// returns 0
first_index_of_one.value();

const auto last_index_of_one = numbers.find_last_index(1);
// returns 8
last_index_of_one.value();

// all_indices_of_one -> { 0, 6, 8 }
const auto all_indices_of_one = numbers.find_all_indices(1);

const auto index_of_nine = numbers.find_first_index(9);
// returns false
index_of_nine.has_value();

remove, insert

#include "functional_vector.h" // instead of <vector>
#include "index_range.h"

functional_vector<int> numbers({1, 4, 2, 5, 8, 3, 1, 7, 1});

// numbers -> functional_vector<int>({1, 4, 2, 5, 3, 1, 7, 1});
numbers.remove_at(4);

// numbers -> functional_vector<int>({4, 2, 5, 3, 1, 7, 1});
numbers.remove_front();

// numbers -> functional_vector<int>({4, 2, 5, 3, 1, 7});
numbers.remove_back();

// numbers -> functional_vector<int>({4, 2, 7});
numbers.remove_range(index_range::start_count(2, 3));

// numbers -> functional_vector<int>({4, 8, 2, 7});
numbers.insert_at(1, 8);

// numbers -> functional_vector<int>({-10, 4, 8, 2, 7});
numbers.insert_front(-10);

// numbers -> functional_vector<int>({-10, 4, 8, 2, 7, 9});
numbers.insert_back(9);

// numbers -> functional_vector<int>({-10, 4, 8, 3, -2, 5, 2, 7, 9});
numbers.insert_at(3, std::vector({3, -2, 5}));

// numbers -> functional_vector<int>({4, -6, 7, -10, 4, 8, 3, -2, 5, 2, 7, 9});
numbers.insert_front(functional_vector({4, -6, 7}));

// numbers -> functional_vector<int>({4, -6, 7, -10, 4, 8, 3, -2, 5, 2, 7, 9, 7, 3});
numbers.insert_back(std::initializer_list({7, 3}));

size/capacity, reserve/resize

#include "functional_vector.h" // instead of <vector>

// numbers.capacity() = 9
// numbers.size() = 9
functional_vector<int> numbers({1, 4, 2, 5, 8, 3, 1, 7, 1});

// numbers -> functional_vector<int>({1, 4, 2, 5, 8});
// numbers.capacity() = 9
// numbers.size() = 5
numbers.resize(5);

// numbers -> functional_vector<int>({1, 4, 2, 5, 8, 0, 0});
// numbers.capacity() = 9
// numbers.size() = 7
numbers.resize(7);

// empty_numbers.capacity() = 0
// empty_numbers.size() = 0
functional_vector<int> empty_numbers;

// empty_numbers.capacity() = 5
// empty_numbers.size() = 0
empty_numbers.reserve(5);

all_of, any_of, none_of

#include "functional_vector.h" // instead of <vector>

functional_vector<int> numbers({1, 4, 2, 5, 8, 3, 1, 7, 1});

// returns true
numbers.all_of([](const auto &number) {
    return number < 10;
});

// returns false
numbers.all_of([](const auto &number) {
    return number > 2;
});

// returns true
numbers.any_of([](const auto &number) {
    return number < 5;
});

// returns false
numbers.any_of([](const auto &number) {
    return number > 9;
});

// returns true
numbers.none_of([](const auto &number) {
    return number < -2;
});

// returns false
numbers.none_of([](const auto &number) {
    return number > 7;
});

Parallel algorithms

Since C++17 several STL algorithms can be executed in parallel.

clang on macOS does not yet fully support the parallel execution model, however on Windows and Linux, a functional_vector supports the following parallel algorithms

for_each_parallel
map_parallel
filter_parallel
sort_parallel
all_of_parallel
any_of_parallel
none_of_parallel

functional_vector's People

Contributors

jkalias avatar iamogunyinka avatar jw2476 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.