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?

+3


source to share


1 answer


I'm not entirely sure if this is what you want, but maybe this helps:

Live here

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.

+3


source







All Articles