Skip to content

Instantly share code, notes, and snippets.

@id-ilych
Last active March 19, 2019 21:52
Show Gist options
  • Save id-ilych/599ac6b9d0b115e0f2425d1234b60860 to your computer and use it in GitHub Desktop.
Save id-ilych/599ac6b9d0b115e0f2425d1234b60860 to your computer and use it in GitHub Desktop.
#include <functional>
#include <optional>
#include <vector>
#include <iostream>
template<typename T>
using Receiver = std::function<void( T )>;
template<typename T, typename U>
using Transformer = std::function<U( T )>;
template<typename T, typename U>
using Chainer = std::function<void( T, Receiver<U> )>;
template<typename T>
using Predicat = std::function<bool( T )>;
template<typename It>
using ValueOf = typename std::iterator_traits<It>::value_type;
template<typename It, typename T, typename U>
bool for_all( It first, It last, std::function<bool( U )> predicate ) {
for ( ; first != last; ++first ) {
if ( !predicate( F( *first ) ) ) {
return false;
}
}
return true;
}
template<typename It, typename U>
void for_each( It first, It last, Chainer<ValueOf<It>, U> chainer, Receiver<U> func ) {
for ( ; first != last; ++first ) {
chainer( *first, func );
}
}
template<typename It, typename R = Receiver<ValueOf<It>>>
void for_each( It first, It last, R func ) {
typedef ValueOf<It> Value;
for_each<It, Value>( first, last, []( Value t, Receiver<Value> f ) { return f( t ); }, func );
}
template<typename T, typename U>
Chainer<T, U> map( Transformer<T, U> transformer ) {
return [=]( T value, Receiver<U> next ) {
next( transformer( value ) );
};
}
template<typename T>
Chainer<T, T> filter( Predicat<T> predicat ) {
return [=]( T value, Receiver<T> next ) {
if ( predicat( value ) ) {
next( value );
}
};
}
template<typename T>
Chainer<T, T> repeat( int times ) {
return [=]( T value, Receiver<T> next ) {
for ( auto i = 0; i < times; ++i ) {
next( value );
}
};
}
template<typename T, typename U, typename V>
Chainer<T, V> operator>>( Chainer<T, U> chainer1, Chainer<U, V> chainer2 ) {
return [=]( T value, Receiver<V> next ) {
chainer1( value, [=]( auto value2 ) {
chainer2( value2, next );
} );
};
}
typedef std::vector<int> Vec;
typedef Vec::value_type Value;
typedef Vec::const_iterator It;
void print( Value value );
void test1( const Vec &vec ) {
for_each( std::begin( vec ), std::end( vec ), []( Value value ) {
print( value );
} );
}
void test1_handmade( const Vec &vec ) {
for ( auto value : vec ) {
print( value );
}
}
void test2( const Vec &vec ) {
for_each<It, int>(
std::begin( vec ), std::end( vec ),
map<int, int>( []( auto value ) { return 3 * value; } )
>> map<int, int>( []( auto value ) { return 2 * value; } ),
[]( int value ) -> void {
print( value );
}
);
}
void test2_handmade( const Vec &vec ) {
for ( auto value : vec ) {
auto a = value * 3;
auto b = a * 2;
print( b );
}
}
void test3( const Vec &vec ) {
for_each<It, int>(
std::begin( vec ), std::end( vec ),
map<int, int>( []( auto value ) { return 1 + value; } )
>> map<int, int>( []( auto value ) { return 1 + value; } )
>> map<int, int>( []( auto value ) { return 1 + value; } )
>> filter<int>( []( auto value ) { return value % 2 == 0; } )
>> map<int, int>( []( auto value ) { return 1 + value; } ),
[]( int value ) -> void {
print( value );
}
);
}
void test3_handmade( const Vec &vec ) {
for ( auto value : vec ) {
auto a = 1 + value;
auto b = 1 + a;
auto c = 1 + b;
if ( c % 2 == 0 ) {
auto d = 1 + c;
print( d );
}
}
}
void test4( const Vec &vec ) {
for_each<It, int>(
std::begin( vec ), std::end( vec ),
map<int, int>( []( auto value ) { return 1 + value; } )
>> map<int, int>( []( auto value ) { return 1 + value; } )
>> filter<int>( []( auto value ) { return value % 2 == 0; } )
>> map<int, int>( []( auto value ) { return 1 + value; } )
>> repeat<int>( 3 ),
[]( int value ) -> void {
print( value );
}
);
}
void test4_handmade( const Vec &vec ) {
for ( auto value : vec ) {
auto a = 1 + value;
auto b = 1 + a;
if ( b % 2 == 0 ) {
auto c = 1 + b;
for ( auto i = 0; i < 3; ++i ) {
print( c );
}
}
}
}
int main() {
const Vec vec{ 1, 2, 3 };
test1( vec );
std::cout << "---" << std::endl;
test1_handmade( vec );
std::cout << "---" << std::endl;
test2( vec );
std::cout << "---" << std::endl;
test2_handmade( vec );
std::cout << "---" << std::endl;
test3( vec );
std::cout << "---" << std::endl;
test3_handmade( vec );
std::cout << "---" << std::endl;
test4( vec );
std::cout << "---" << std::endl;
test4_handmade( vec );
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment