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