类似于lisp的c ++使用参数包

时间:2015-07-26 15:45:54

标签: c++ c++11 lambda c++14

我对this问题很感兴趣,所以我不得不尝试一下,因为它让我想起了我非常喜欢的口齿不清。该问题的例子:

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    
}

最终我得到了更多的多态lambda,这使得它看起来像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

现在,如果我想要一个打印功能,我做了,我必须写它:

auto print = [](auto i)
{
    std::cout << i << " ";
    return i;
};

然后将其映射到参数包中的每个参数。

这不是真正的lisp,我想知道是否有办法使用lisp中使用的car / cdr样式递归遍历参数包。显然,必须使用列出lambda返回的闭包。

另外,我知道参数包不应该用于这样的事情。

编辑:

我设法使用模板实现递归打印:

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...);
    });
}

但是现在我遇到了返回值的递归函数的问题。假设我想要一个filter / remove-if函数,它返回一个符合提供的谓词给出的要求的元素列表。目前我正在使用每个元素的std :: pair(就像在链接的问题中一样),如果在打印时跳过该对,则包含一个标志。有没有办法在不需要标志的情况下实际返回那些元素的列表?

1 个答案:

答案 0 :(得分:3)

我不太确定这是否是你想要的,但也许有帮助:

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);
 });
};

虽然这只适用于编译时已知的列表,但是终止是通过模板参数完成的。

根据您引用的问题,在最上面的答案中,最后有一个链接: https://gist.github.com/Manu343726/fb57746274fffc043c2a

foldl_值得一看,它似乎完成了我必须使用帮助器结构。

可变值为working,但必须在编译时知道列表及其元素类型的长度。