Skip to content

Instantly share code, notes, and snippets.

@reuk
Created January 8, 2014 22:43
Show Gist options
  • Save reuk/8325948 to your computer and use it in GitHub Desktop.
Save reuk/8325948 to your computer and use it in GitHub Desktop.
//
// main.cpp
// functional
//
// Created by Reuben Thomas on 08/01/2014.
// Copyright (c) 2014 Reuben Thomas. All rights reserved.
//
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
#include <numeric>
// basic functional patterns
template <typename T, typename U, typename FuncType>
T map (const U & u, const FuncType & f)
{
T ret (u.size());
std::transform (u.begin(), u.end(), ret.begin(), f);
return ret;
}
template <typename U, typename FuncType>
U filter (const U & u, const FuncType & f)
{
U ret;
std::remove_copy_if
( u.begin()
, u.end()
, std::back_inserter (ret)
, std::not1 (f)
);
return ret;
}
template <typename T, typename U, typename FuncType>
T reduce (const U & u, const T & t, const FuncType & f)
{
return std::accumulate (u.begin(), u.end(), t, f);
}
// functors for working with std::pairs
template <typename T, typename U>
struct getFirst: public std::unary_function<std::pair<T, U>, T>
{
T operator() (const std::pair<T, U> & p) const {return p.first;}
};
template <typename T, typename U>
struct getSecond: public std::unary_function<std::pair<T, U>, U>
{
U operator() (const std::pair<T, U> & p) const {return p.second;}
};
// function composition!
template <typename T, typename U>
struct composer: public std::unary_function<typename T::argument_type, typename U::result_type>
{
protected:
T t;
U u;
public:
explicit composer (const T & t, const U & u): t (t), u (u) {}
typename U::result_type operator() (const typename T::argument_type & arg) const
{
return u (t (arg));
}
};
template <typename T, typename U>
composer<T, U> compose (const T & t, const U & u)
{
return composer<T, U> (t, u);
}
// output functor
template <typename T>
struct printer: public std::unary_function<T, void>
{
void operator() (const T & t) const {std::cout << t << " ";}
};
// let's try it all out...
int main(int argc, const char * argv[])
{
std::vector<std::pair<double, double> > v;
v.push_back (std::pair<double, double> (0.1, 7));
v.push_back (std::pair<double, double> (-2, 5.29));
v.push_back (std::pair<double, double> (1, 0));
v.push_back (std::pair<double, double> (500, -7.1));
std::vector<double> l = map<std::vector<double> >
( v
, compose (getFirst<double, double>(), std::bind1st (std::plus<double>(), 2.0))
);
std::for_each (l.begin(), l.end(), printer<double>());
std::cout << std::endl;
std::vector<std::pair<double, double> > d = filter
( v
, compose (getFirst<double, double>(), std::bind2nd (std::greater_equal<double>(), 0.0))
);
std::for_each (d.begin(), d.end(), compose (getFirst<double, double>(), printer<double>()));
std::cout << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment