Lambda Expression Library
Single header (after fusing) library with no external dependencies.
auto is_right_triangle = _a * _a + _b *_b == _c * _c;
is_right_triangle(3, 4, 5);
Lambda functions in c++ are cool, very cool. But they give quite some overhead in syntax requirements, which obscures very little functions. Consider:
auto is_even = [](auto i) { return i % 2 == 0; };
It is very short, nice lambda, but the actual condition is only around half of its body. Now lets see how it would look in lambda expression:
auto is_even = _i % 2 == 0;
Shorted, right? And, for me, much cleaner.
using namespace lel;
auto plus_one = _x + 1;
auto multiply = _x * _y;
auto is_less = _1 < _2;
assert(plus_one(2) == 3);
assert(multiply(2, 3) == 6);
assert(is_less(2, 5));
auto compute_something = 1 + _x * 3 - _y * _y + _x * _z;
assert(3 == compute_something(1, 2, 3));
auto first_arg = lel::placeholder<'1'>();
auto second_arg = lel::placeholder<'2'>();
auto not_equal = first_arg != second_arg;
assert(not_equal(2, 3));
auto add_of_vectors = *((*_x)[_1]) + **(_y[_2]);
auto x_vec = std::make_unique<std::vector<std::unique_ptr<int>>>();
x_vec->push_back(std::make_unique<int>(1));
x_vec->push_back(std::make_unique<int>(2));
x_vec->push_back(std::make_unique<int>(3));
x_vec->push_back(std::make_unique<int>(4));
auto y_vec = std::vector<std::unique_ptr<std::unique_ptr<int>>>();
y_vec.push_back(std::make_unique<std::unique_ptr<int>>(std::make_unique<int>(6)));
y_vec.push_back(std::make_unique<std::unique_ptr<int>>(std::make_unique<int>(7)));
y_vec.push_back(std::make_unique<std::unique_ptr<int>>(std::make_unique<int>(8)));
y_vec.push_back(std::make_unique<std::unique_ptr<int>>(std::make_unique<int>(9)));
assert((4+7) == (add_of_vectors(3, 1, x_vec, y_vec)));
int x = 5;
auto add_to_x = _(x) += _y;
add_to_x(8);
assert(x == 13);
auto sum = _x + _y + _z;
assert(6 == sum(1, 2, 3));
assert(6 == sum(1)(2, 3));
assert(6 == sum(1, 2)(3));
assert(6 == sum(1)(2)(3));
auto duplicate = [](int i) {
return i * 2;
};
auto call_with = _x._(_y);
assert(8 == call_with(duplicate, 4));
auto do_with_three = _x._(3);
assert(6 == do_with_three(duplicate));
auto times_two = _(duplicate)._(_y);
assert(10 == times_two(5));
auto agregate = [](int a, int b, int c, int d) {
return a + b + c + d;
};
auto reduce = _(agregate)._(_a, _b, _c, _d);
assert(20 == reduce(2, 4, 6, 8));
struct Object {
Object(int value) : value(value) {}
int Method(int arg) { return value * arg; }
int value;
};
Object object(5);
auto get_value = (&_x->*_y);
auto set_value = get_value = _z;
set_value(object, &Object::value, 8);
assert(get_value(object, &Object::value) == 8);
auto call_method = get_value._(_z);
assert(call_method(object, &Object::Method, 3) == 24);
Files There are two ways of including LeL:
-
in multiple headers, as it is in repository; everything is in
include
directory -
in one fused-header;
script/fuse
will fuse all intobuild/lel.hpp
API The only things that should be used are:
namespace lel
- with predefined placeholders_
- instance oflel::reference
class_1
..._9
/ instances oflel::placeholder
class_A
..._Z
|_a
..._z
/placeholder
- template alias for placeholders creationreference
- class for wrapping objects in a reference
#include "lel.hpp"
auto use_with_namespace = lel::_x + 2;
auto create_your_own = lel::placeholder<'a'>();
/* or */ using namespace lel;
auto like_that = 1 * _2;
Implementation Templates, so many templates. Cool stuff!
The separate types of placeholders are distinguist by template variable of
type (by default, can be changed) char.
So Placeholder<'a'>
and Placeholder<'A'>
are different types.
You can use any combination of them (only numbers, numbers and letters, etc) in any order or degree. The important thing is the arguments during evaluation will be assigned with alphabetic (ASCII alphabetic) order.
So:
auto expr = _1 - _x;
assert(-1 == expr(2, 3));
assert( 1 == expr(3, 2));
There is a bunch of tests but they are not needed for normal usage. You can run all of them with cmake:
mkdir build
cd build
cmake .. -DENABLE_TESTING=ON
cmake --build .
ctest -VV
TBD
Yes, the same concept but this one uses a little bit newer C++. However the idea for this library came out independently.