【问题标题】:Lisp like C++ function calling with std::tuple and fold expressionsLisp 像 C++ 函数调用 std::tuple 和折叠表达式
【发布时间】:2021-04-23 22:38:10
【问题描述】:

我能想到的关于 Lisp 的最基本的事情就是如何调用函数。对于那些不知道如何在 Lisp 中做到这一点的人来说,是这样的:

(fun1 a b (fun2 c d))
; c and d are parameters to the function fun2,
; and a, b and the result of fun2 are parameters
; to the function fun 1

嗯,我想在 C++ 中使用 std::tuple 和折叠表达式做类似的事情。基本上,我有一个包含 2 个元素的元组,第一个是我要调用的函数,第二个是另一个带有参数的元组。我能够使这个概念适用于 1 个函数,并使用以下代码将“Lisp 元组”放入另一个元组中:

 auto add = [](auto ... args){ return (args + ...); };
 auto t1_args = std::make_tuple(10, 5);
 auto t1 = std::tie(add, t1_args);
 auto t_m = std::tie(t1);

 auto result = std::apply([](auto ... args){
     return (std::apply(std::get<0>(args), std::get<1>(args...)), ...);
 }, t_m);

 std::cout << result << std::endl; // prints 15

但是我不能用多个函数,多个“Lisp 元组”,一个在另一个里面。这里有人可以帮我吗?也许用另一种方法来制作“Lisp 元组”,但我真的不知道如何让它工作。

【问题讨论】:

    标签: c++ c++17 lisp stdtuple fold-expression


    【解决方案1】:

    您必须递归地评估每个参数,例如:

    template <typename T>
    auto eval(T t)
    {
        return t;
    }
    
    template <typename ...Ts>
    auto eval(std::tuple<Ts...> tuple)
    {
        return std::apply([](auto... args){ return std::invoke(eval(args)...); }, tuple);
    }
    

    Demo.

    【讨论】:

    • 您还需要一个引号标记(如在 lisp 中)。
    • @Yakk-AdamNevraumont 我认为添加:) 或以其他方式表明您在开玩笑可能是个好主意,因为否则您的评论可能会令人困惑。它也似乎足够合理,很难通过评论标志删除。
    • @cig 瑙;如果你想将一个元组传递给一个函数,你需要引用它。 make_tupke 函数对象是不够的,因为它只“引用”了一层。依次返回的元组应该有效地传递给eval,因此其他黑客也不起作用。您需要eval 的支持。可能是 quote( tuple ) eval 取消装箱(但不评估内容),甚至可能是使下一个元组跳过 eval 或类似的引用对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-08
    • 2015-02-19
    相关资源
    最近更新 更多