Существует ли эквивалентность lisp cdr для c ++ std :: list? - PullRequest
0 голосов
/ 20 апреля 2020

У некоторых людей есть свой класс списка с car (например, head) cdr (например, tail). Мне интересно, можно ли использовать std::list для поддержки этих операций. car тривиально. Но я не знаю, как можно подражать cdr.

1 Ответ

3 голосов
/ 21 апреля 2020

В C ++ 20 мы получаем библиотеку Ranges. Я еще не рассматривал это подробно, но я подозреваю, что здесь могут помочь поддиапазоны или представления.

Pre C ++ 20

В C ++ (до сих пор) мы часто не передавайте напрямую список (или другой контейнер), а скорее пару итераторов. Взгляните на библиотеку <algorithm>: такие функции, как std::sort, не принимают ссылку на контейнер - вместо этого они принимают итератор first и итератор last.

Важно: last указывает не на последний элемент, а на одно место за ним - то же, что даст вам std::list::end(). Это означает, что когда first == last у вас есть «пустой список»

В мире, предшествующем C ++ 20, вы обычно пишете свой код таким же образом. Одним из преимуществ этого является то, что если у вас есть пара итераторов first и last, то (до first != last) *first - это car, а пара std::next(first) и last это cdr. Итак:

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

становится чем-то вроде

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

(я знаю, что некоторые люди не согласятся с тем, как я отформатировал этот условный оператор на нескольких строках - но я хотел отразить Lisp стиль.)

...