1

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.

zjk
  • 2,043
  • 3
  • 28
  • 45

1 Answers1

3

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

Allison Lock
  • 2,375
  • 15
  • 17