【问题标题】:Is there a lisp cdr equivalence for c++ std::listc++ std::list 是否有 lisp cdr 等价性
【发布时间】:2020-04-20 14:02:12
【问题描述】:

有些人的自定义列表类带有car(例如head)cdr(例如tail)。我想知道std::list 是否可以用来支持这些操作。 car 是微不足道的。但是我不知道cdr是怎么模拟出来的。

【问题讨论】:

  • 如果你想就地修改列表,那么pop_front。如果你想复制尾部,那么std::list<SomeType>{std::next(mylist.begin()), mylist.end()};
  • C++ 列表不会暴露它们的结构,而这是“正确”的 Lisp 列表(Newell-Shaw-Simon 列表)所需要的。
  • @IgorTandetnik 但是pop_front 丢失了原始列表?使用 lisp cdr,原始列表仍然可用。
  • 你看过我评论的第二部分了吗?
  • @IgorTandetnik:复制尾部不是cdr 所做的。

标签: c++ lisp cdr


【解决方案1】:

在 C++20 中,我们获得了 Ranges 库。我还没有详细研究它,但我怀疑子范围或视图可能会有所帮助。

Pre C++20

在 C++ 中(直到现在),我们通常不直接传递列表(或其他容器),而是传递一对迭代器。看看<algorithm> 库:像std::sort 这样的函数不引用容器——相反,它们采用first 迭代器和last 迭代器。

重要提示:last 指向最后一项,而是指向它之外的一个位置 - 与 std::list::end() 给出的相同。这意味着当first == last 你有一个“空列表”

在 C++20 之前的世界中,您通常会以相同的方式编写代码。这样做的好处之一是,如果你有一对迭代器firstlast,那么(只要first != last*first 就是car,并且一对std::next(first) 和@ 987654334@ 是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 风格。)

【讨论】:

    猜你喜欢
    • 2010-12-04
    • 1970-01-01
    • 2015-11-03
    • 2020-04-23
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    • 2023-03-07
    • 2021-08-04
    相关资源
    最近更新 更多