Skip to content

Instantly share code, notes, and snippets.

@harsh183
Last active April 23, 2021 12:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save harsh183/f06e3e71d48ecffae1e5d5de12e1af11 to your computer and use it in GitHub Desktop.
Save harsh183/f06e3e71d48ecffae1e5d5de12e1af11 to your computer and use it in GitHub Desktop.
Basic and cool functional programmig concepts in C++14 onwards. Lots of auto abuse too for interesting type inference and results. Useful as a quick reference too. (Formatting is a bit wonky bc gist is weird sorry)
#include <iostream>
#include <string>
#include <vector>
#include <functional> // std::function, std::bind
#include <algorithm> // std::transform, std::remove_if
#include <numeric> // std::accumulate
using namespace std;
using namespace std::placeholders; // for _1, _2, _3 etc. for bind
// See: https://www.codeproject.com/Articles/1267996/Functional-Programming-in-Cplusplus
// Learning/reference thing I made for myself lol
int multiply(int a, int b) {
return a*b;
}
auto add10(int a) {
return a + 10;
}
int main() {
// Lambdas
auto hello = [] () { cout << "Hello world" << endl; };
hello();
// how to pass args and return, auto can infer return too
auto sum = [] (int a, int b) { return a + b; };
auto sub = [] (int a, int b) -> int { return a - b;};
cout << sum(5, 10) << endl; // => 15
cout << sub(10, 5) << endl; // => 5
// the point of the [] is for scope actually
int answer_to_everything = 42;
auto answer_any_question = [answer_to_everything] (string question) {
return answer_to_everything;
};
cout << answer_any_question("Will I ever find love?") << endl; // => 42
// understanding std::function
// a generic all powerful wrapper that shows the type of the function
// int(int, int) - returns int using two ints
std::function<int(int, int, int, int)> multiply4 = [] (int a, int b, int c, int d) -> int {
return multiply(multiply(a, b),
multiply(c, d));
};
cout << "1 * 2 * 3 * 4 = " << multiply4(1, 2, 3, 4) << endl; // => 24
// bind
// we can reorder or hard code things
// note that counting is from _1, here
auto multiply3 = bind(multiply4, 1, _1, _2, _3);
cout << "2 * 3 * 4 = " << multiply3(2, 3, 4) << endl; // => 24
// lambdas can also type infer (unlike functions too take that) - use it wisely
cout << "auto add10(int a) - " << add10(40) << endl;
auto divide = [] (auto num, auto dem) { return num/dem; };
cout << "1/2 - " << divide(1, 2) << endl; // => 0
cout << "1.0/2 - " << divide('c', 2) << endl; // => 0.5
// Higher order functions
auto print_array_ish = [] (auto arr, auto size) {
cout << "[ ";
for (auto i = 0; i < size; i++) {
cout << arr[i] << ", ";
}
cout << "]" << endl;
};
int primes[] = {2, 3, 5, 7, 11, 13, 17, 19};
print_array_ish(primes, 8);
// we can pass lambdas through scope too
auto print_vector = [print_array_ish] (auto vec) { print_array_ish(vec, vec.size()); };
vector<int> numbers {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
vector<float> others {-1.5, 4, -3, 42.43};
print_vector(numbers); // => [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ]
print_vector(others); // => [ -1.5, 4, -3, 42.43, ]
// foreach
for_each(numbers.begin(), numbers.end(),
[](float num) { cout << num << " ";});
cout << endl; // => 1 2 3 4 5 6 7 8 9 10
// map - transform
vector<float> others_squared(others.size()); // make sure to allocate size
transform(others.begin(), others.end(), others_squared.begin(),
[](auto num) { return num * num; }
);
print_vector(others_squared); // => [ 2.25, 16, 9, 1800.3, ]
// filter - remove if (reversed filter basically)
// Note: the erase is needed to shrink back otherwise garbage values are still present
// on arrays we will have to manually calculate the sizes
vector<int> teens {13, 14, 15, 16, 17, 18, 19};
teens.erase( remove_if (teens.begin(), teens.end(), [] (int n) { return n%2 !=0; }), teens.end());
print_vector(teens); // => [ 14, 16, 18, ]
// reduce/fold - accumulatve
// default - sum()
auto reduced_sum = accumulate(begin(numbers), end(numbers), 0);
cout << "sum - reduce/fold: " << reduced_sum << endl; // => 55
// custom function accumulate
auto multiplied_everything = accumulate(begin(numbers), end(numbers), 1, multiply);
cout << "multiplied: " << multiplied_everything << endl; // => 3628800
// custom lambda accumulate
auto reduced_sub = accumulate(begin(numbers), end(numbers), 0, sub);
cout << "sub all: " << reduced_sub << endl; // => -55
// custom higher order lambda
auto bin_operation_on_4_numbers = [] (function<int(int, int)> operation,
auto a, auto b, auto c, auto d) {
return operation( operation(a, b), operation(c, d));
};
cout << "sum higher order" << bin_operation_on_4_numbers(sum, 1, 10, 200, 4000) << endl;
// => 4210
}
// TODO: Curry, pure, immuatable
@harsh183
Copy link
Author

MIT License

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment