c++lispcdr

Is there a lisp cdr equivalence for c++ std::list


Some people have their custom list class with car(eg. head) cdr(eg. tail). I'm wondering if std::list can be used to support these operations. car is trivial. But I don't know how cdr can be emulated.


Solution

  • In C++20, we're getting the Ranges library. I haven't looked at it in much detail yet, but I suspect that subranges or views might help here.

    Pre C++20

    In C++ (up until now), we often don't directly pass a list (or other container) around, but rather a pair of iterators. Take a look at the <algorithm> library: functions like std::sort don't take a reference to a container - instead, they take a first iterator and an last iterator.

    Important: last does not point to the last item, but rather one place beyond it - the same as std::list::end() would give you. This means that when first == last you have "an empty list"

    In a pre-C++20 world, you would generally write your code in the same way. One of the advantages of doing this is that if you have a pair of iterators first and last, then (as long as first != last) *first is the car, and the pair std::next(first) and last is the cdr. So:

    (defun sum (list)
      (if (null list)
          0
        (+ (car list) (sum (cdr list)))))
    

    becomes something like

    template <class ForwardIter>
    int sum(ForwardIter first, ForwardIter last) {
      return (first == last)
               ? 0
               : (*first) + sum(std::next(first), last);
    }
    

    (I know some people would disagree with how I've formatted that conditional operator over multiple lines - but I wanted to mirror the Lisp style.)