3

I was intrigued by this question, so I had to try it out because it kind of reminded me of lisp which I absolutely loved. Example from that 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    
}

Eventually I got some more polymorphic lambdas which further 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, which 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 parameters in the parameter pack.

That's not really lisp-like and I'm wondering if there's a way to recursively go through the parameter pack using car/cdr style that's used in lisp. Obviously the closure that list lambda returns would have to be used.

Also, I'm aware that parameter packs shouldn't really be used for things like this.

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'm having problems with recursive functions that return values. Let's say I want to have a filter/remove-if function which returns a list of elements which meet the requirement given by the provided predicate. Currently I'm using a std::pair (just like in the linked question) per element, which contains a flag if the pair should be skipped while printing. Is there a way to actually return the list of only those elements without the need for flags?

Community
  • 1
  • 1
rndm
  • 137
  • 1
  • 9
  • 1
    so, the usage you are looking for is `print (l)` where `auto l = list (-1, 2, 3, 4, 5, 6)`, or is it simply `print (1,2,3)`? – Filip Roséen - refp Jul 26 '15 at 18:19
  • I updated the original question since I managed to make printing recursive. Although I'm sure I already tried the same approach, and had some compiler errors. – rndm Jul 26 '15 at 18:38

1 Answers1

3

I'm not quite sure whether this is what you want, but maybe it 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);
 });
};

Though this will only work with lists that are known during compile time, since the termination is done via a template parameter.


From the question you referenced, in the top answer there's a link at the end: https://gist.github.com/Manu343726/fb57746274fffc043c2a

The foldl_ there's worth a look, it seems to accomplish what I had to use helper structs for.


Mutable values are working, but the length of the list and its elements types must be known at compile time.

Daniel Jour
  • 15,896
  • 2
  • 36
  • 63
  • "... lists that are known during compile time". You mean where the length, and element types, of the list are known at compile time? But not the values? – Aaron McDaid Jul 26 '15 at 18:29
  • 1
    Yes, I guess this applies to all this code, just wanted it to make clear. – Daniel Jour Jul 26 '15 at 18:30
  • 1
    Thanks for answering. I updated the original question since I managed to make printing recursive. But now I'm facing a different problem. Probably should've used the filter/remove-if example instead of printing. – rndm Jul 26 '15 at 18:39