0

The most basic thing I can think about Lisp is how to call functions. To those who doesn't know how to do that in Lisp, is something like that:

(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

Well, I want to do something like that in C++ using std::tuple and fold expressions. Basically, I have a tuple with 2 elements, the firts is a function that i want to call, and the second is a another tuple with the arguments. I was able to make this concept works with 1 function and putting the "Lisp tuple" in another tuple with the following code:

 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

But I can't do that with multiple functions, multiple "Lisp tuples", one inside the other. Someone here could help me with that? Perhaps with another way to make the "Lisp tuple", but I really don't know how to make this works.

1 Answers1

1

You have to evaluate each argument recursively, something like:

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.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • You'll also want a quote token (like in lisp). – Yakk - Adam Nevraumont Jan 19 '21 at 19:25
  • @Yakk-AdamNevraumont I think adding a `:)` or otherwise indicating that you're joking is probably a good idea, since your comment could be confusing otherwise. It also *seems* reasonable enough that it would be hard to delete via a comment flag. – cigien Jan 19 '21 at 22:32
  • @cig naw; if you want to pass a tuple to a function you'll need to quote it. A `make_tupke` function object isn't enough as it only "quotes" one level. The returned tuple in turns should be valid to pass to `eval`, so other hacks won't work either. You need support in `eval`. Could be `quote( tuple )` that eval unboxes (but does not eval contents) or even a quote object that makes the next tuple skip eval or something like that. – Yakk - Adam Nevraumont Jan 19 '21 at 22:44