Lisp-like C ++ using option packages
I was intrigued by this question , so I had to try it out because it reminded me of lisp, which I absolutely loved. An example from this question:
auto list = [](auto ...xs) {
return [=](auto access) { return access(xs...); };
};
auto length = [](auto xs) {
return xs([](auto ...z) { return sizeof...(z); });
};
int main()
{
std::cout << length(list(1, '2', "3")); // 3
}
I ended up with a few more polymorphic lambdas that made it look like lisp:
auto l = list(-1, 2, 3, 4, 5, 6);
cons(unary::map(unary::inc)
(binary::map(binary::add)
(cdr(l), 1)), list(12, 13, 14, 15, 16)))
// just an example, it doesn't really look that much like lisp, but still I was amused
Now if I wanted a print function that I did, I had to write it like:
auto print = [](auto i)
{
std::cout << i << " ";
return i;
};
and then map it to each of the options in the option pack.
This is not really lisp -like, and I am wondering if there is a way to recursively traverse the parameter pack using the car / cdr style that lisp uses. Obviously, you will need to use a closure that returns a lambda list.
Also, I know that parameter packs shouldn't really be used for this kind of thing.
EDIT:
I managed to implement recursive printing using templates:
template<typename First>
void print_helper(First f)
{
std::cout << f << std::endl;
}
template<typename First, typename... Rest>
void print_helper(First f, Rest... r)
{
std::cout << f << " ";
print_helper(r...);
}
template<typename Lambda>
void print(Lambda l)
{
l([=](auto... elements)
{
print_helper(elements...);
});
}
But now I am having trouble with recursive functions returning values. Let's say I want to have a filter / remove-if function that returns a list of elements that satisfy the requirement given by the predicate. I am currently using std :: pair (as in the linked question) for each item that contains a flag if a pair should be skipped during printing. Is there a way to actually return a list of only those elements without the need for flags?
source to share
I'm not entirely sure if this is what you want, but maybe this helps:
template<bool = true>
struct printer {
template<typename List>
static void run (List xs) {
return xs([](
auto first /* the car */,
auto... rest /* the cdr, more or less */) {
cout << first << " ";
printer<(sizeof...(rest) > 0)>::run(
list(rest...)); // building a new list every time, tough
});
}
};
template<>
struct printer<false> {
template<typename List>
static void run (List xs) {}
};
auto print = [](auto xs) {
return xs([=](auto ...z) {
printer<(sizeof...(z) > 0)>::run(xs);
});
};
Although this will only work on lists that are known at compile time, since completion is done using a template parameter.
From the question you linked to, the top answer has a link at the end: https://gist.github.com/Manu343726/fb57746274fffc043c2a
foldl_
it's worth a look there, looks like I had to use helper structures for.
Variable values work , but the length of the list and its element types must be known at compile time.
source to share