Recognition: unknown
Persistent Iterators with Value Semantics
Pith reviewed 2026-05-10 11:39 UTC · model grok-4.3
The pith
Persistent iterators snapshot a container's version at creation to enable safe value-semantic operations on a local copy.
A machine-rendered reading of the paper's core claim, the machinery that carries it, and where it could break.
Core claim
Persistent iterators snapshot the version of their underlying container at creation. Iterator operations thereafter execute against this local copy of the container, delivering true value semantics in which rebinding a variable to a fresh persistent value leaves all previous versions intact and accessible.
What carries the argument
The persistent iterator, which holds a private snapshot of the container and routes all read and write operations through that snapshot.
If this is right
- Iterator invalidation hazards disappear because each iterator works on its own snapshot.
- Aliasing and data-race problems are avoided since operations never mutate the original container through the iterator.
- Value semantics become available inside iteration loops, allowing safe rebinding of variables to new container versions.
- Existing iterator-based algorithms from the STL can be reused without rewriting them in a recursive or combinator style.
- The library supplies persistent vectors, maps, sets, and strings whose iterator interfaces match the familiar STL pattern.
Where Pith is reading between the lines
- The same snapshot-and-local-copy pattern could be applied to other mutable abstractions such as file handles or database cursors.
- Because each iterator is isolated, the design naturally supports safe concurrent traversal of different versions of the same logical container.
- Programmers could mix persistent and non-persistent containers in the same codebase by choosing iterator type at the point of use.
Load-bearing premise
The persistent data structures and their local copies can be implemented so that asymptotic costs stay comparable to ordinary containers without large constant-factor or memory overhead in practice.
What would settle it
A direct performance comparison showing that traversal, insertion, or lookup through persistent iterators is asymptotically slower or uses asymptotically more memory than the corresponding operations on standard containers.
Figures
read the original abstract
Iterators are a fundamental programming abstraction for traversing and modifying elements in containers in mainstream imperative languages such as C++. Iterators provide a uniform access mechanism that hides low-level implementation details of the underlying data structure. However, iterators over mutable containers suffer from well-known hazards including invalidation, aliasing, data races, and subtle side effects. Immutable data structures, as used in functional programming languages, avoid the pitfalls of mutation but rely on a very different programming model based on recursion and higher-order combinators rather than iteration. However, these combinators are not always well-suited to expressing certain algorithms, and recursion can expose implementation details of the underlying data structure. In this paper, we propose persistent iterators -- a new abstraction that reconciles the familiar iterator-based programming style of imperative languages with the semantics of persistent data structures. A persistent iterator snapshots the version of its underlying container at creation, ensuring safety against invalidation and aliasing. Iterator operations operate on the iterator-local copy of the container, giving true value semantics: variables can be rebound to new persistent values while previous versions remain accessible. We implement our approach in the form of LibFPP -- a C++ container library providing persistent vectors, maps, sets, strings, and other abstractions as persistent counterparts to the Standard Template Library (STL). Our evaluation shows that LibFPP retains the expressiveness of iterator-based programming, eliminates iterator-invalidation, and achieves asymptotic complexities comparable to STL implementations. Our design targets use cases where persistence and safety are desired, while allowing developers to retain familiar iterator-based programming patterns.
Editorial analysis
A structured set of objections, weighed in public.
Referee Report
Summary. The paper proposes persistent iterators as a new abstraction for C++ that snapshot the version of an underlying persistent container (e.g., vector, map) at creation time. Iterator operations then act on an iterator-local copy, delivering value semantics, immunity to invalidation and aliasing, and compatibility with familiar imperative iterator-based code. The design is realized in the LibFPP library, which supplies persistent counterparts to STL containers; the abstract asserts that the library preserves expressiveness while achieving asymptotic complexities comparable to standard STL implementations.
Significance. If the efficiency claims hold, the work offers a practical bridge between imperative iterator idioms and persistent data structures, allowing developers to retain STL-style traversal without mutation hazards. This could be relevant for concurrent, versioned, or safety-critical C++ codebases that currently must choose between mutable containers with invalidation risks or a full shift to recursive/functional styles.
major comments (2)
- [Abstract] Abstract: the central claim that LibFPP 'achieves asymptotic complexities comparable to STL implementations' is unsupported by any derivation, benchmark data, or implementation description. The text provides only the high-level design statement; without evidence that iterator-local copies incur only logarithmic (or better) overhead via structural sharing, the practicality assertion cannot be evaluated.
- [Design description] Design description (persistent iterators section): the mechanism of 'iterator-local copy of the container' is presented as cheap due to persistence, yet no concrete representation (e.g., how a persistent vector or map maintains structural sharing when an iterator is created) or complexity analysis is supplied. If the local copy is not a constant-time persistent reference but a full duplication, algorithms that instantiate many iterators (nested loops, std::for_each with side effects) would incur linear space per iterator and potentially quadratic total cost, directly contradicting the comparable-complexity guarantee.
Simulated Author's Rebuttal
We thank the referee for the positive assessment of the significance of our work and for the constructive major comments. We agree that the current manuscript would benefit from more explicit support for the complexity claims and a more detailed description of the implementation. Below we respond to each comment and outline the revisions we will make to the next version of the paper.
read point-by-point responses
-
Referee: [Abstract] Abstract: the central claim that LibFPP 'achieves asymptotic complexities comparable to STL implementations' is unsupported by any derivation, benchmark data, or implementation description. The text provides only the high-level design statement; without evidence that iterator-local copies incur only logarithmic (or better) overhead via structural sharing, the practicality assertion cannot be evaluated.
Authors: We acknowledge that the abstract's claim would be stronger with direct supporting material. The manuscript states that evaluation demonstrates comparable complexities, but we agree the abstract itself provides no derivation or data. In revision we will update the abstract to briefly note that complexities are achieved via structural sharing (with full details and benchmarks in the evaluation section) and add a short complexity paragraph early in the design description. This will make the practicality assertion evaluable without requiring the reader to reach later sections. revision: yes
-
Referee: [Design description] Design description (persistent iterators section): the mechanism of 'iterator-local copy of the container' is presented as cheap due to persistence, yet no concrete representation (e.g., how a persistent vector or map maintains structural sharing when an iterator is created) or complexity analysis is supplied. If the local copy is not a constant-time persistent reference but a full duplication, algorithms that instantiate many iterators (nested loops, std::for_each with side effects) would incur linear space per iterator and potentially quadratic total cost, directly contradicting the comparable-complexity guarantee.
Authors: This is a valid concern about the current level of detail. The manuscript describes the iterator-local copy at a high level but does not specify the underlying representation or analyze space costs for multiple iterators. We will revise the persistent iterators section to describe LibFPP's concrete structures (path-copying trees for vectors and maps) and explain that an iterator stores only a persistent root reference obtained in constant time. Operations then traverse the shared structure at logarithmic cost. We will add a complexity table and a brief argument showing that space remains proportional to distinct versions rather than the number of iterators, directly addressing the risk of quadratic blow-up. revision: yes
Circularity Check
No circularity: design proposal with independent implementation claims
full rationale
The paper introduces persistent iterators as a new abstraction reconciling iterator style with persistent data structures, implemented in LibFPP. No equations, fitted parameters, or first-principles derivations appear in the abstract or described content. Claims of comparable asymptotic complexity rest on evaluation and implementation details rather than reducing to self-definitions, self-citations, or renamed inputs. The central design (snapshotting versions for value semantics) is presented as a proposal, not derived from prior results by the same authors in a load-bearing way. This matches the default expectation of no significant circularity.
Axiom & Free-Parameter Ledger
axioms (1)
- domain assumption Persistent data structures can be implemented with efficient path-copying or similar techniques.
Reference graph
Works this paper leans on
-
[1]
Technical Report 14882:2024
2024.Programming Languages — C++. Technical Report 14882:2024. ISO/IEC
2024
-
[2]
Driscoll, N
J. Driscoll, N. Sarnak, D. Sleator, and R. Tarjan. 1986. Making data structures persistent. InSymposium on Theory of computing. ACM
1986
-
[3]
URL: https://drops.dagstuhl.de/entities/document/10.4230/LIPIcs
J. Eyolfson and P. Lam. 2016. C++ const and immutability: an empirical study of writes-through-const. InEuropean Conference on Object-Oriented Programming. Schloss Dagstuhl – Leibniz-Zentrum für Informatik. doi:10.4230/LIPIcs. ECOOP.2016.8
-
[4]
Gamma, R
E. Gamma, R. Helm, R. Johnson, and J. Vlissides. 1995.Design patterns: elements of reusable object-oriented software. Addison-Wesley
1995
-
[5]
R. Hinze and R. Paterson. 2006. Finger trees: a simple general-purpose data structure.Journal of Functional Programming 16, 2 (2006), 197–217. doi:10.1017/S0956796805005769
-
[6]
G. Huet. 1997. The Zipper.Journal of Functional Programming7, 5 (1997), 549–554. doi:10.1017/S0956796897002864
-
[7]
Josuttis
N. Josuttis. 2024.Healing the Filter View. Technical Report P3329R0. ISO/IEC JTC1/SC22/WG21 C++ Standards Committee. https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3329r0.pdf WG21 paper
2024
-
[8]
J. Lakos. 1996.Large-Scale C++ Software Design. Addison-Wesley
1996
-
[9]
Persistent Iterators with Value Semantics
Yihe Li and Gregory Duck. 2026.Artifact for the paper "Persistent Iterators with Value Semantics" - Version 2. doi:10. 5281/zenodo.19392634
2026
-
[10]
Meta. 2026. Folly: An open-source C++ library developed and used at Facebook. https://github.com/facebook/folly
2026
-
[11]
Y. Nikolakopoulos, A. Gidenstam, M. Papatriantafilou, and P. Tsigas. 2015.Of Concurrent Data Structures and Iterations. Springer International Publishing, Cham, 358–369. doi:10.1007/978-3-319-24024-4_20
-
[12]
C. Okasaki. 1995. Simple and efficient purely functional queues and deques.Journal of Functional Programming5, 4 (1995), 583–592. doi:10.1017/S0956796800001489
-
[13]
Oracle Corporation. 2026. Java Collections Framework. https://docs.oracle.com/en/java/javase/21/docs/api/java.base/ java/util/doc-files/coll-overview.html
2026
-
[14]
J. Puente. 2017. Persistence for the masses: RRB-vectors in a systems language. InInternational Conference on Functional Programming. ACM. doi:10.1145/3110260
-
[15]
Python Software Foundation. 2026. Iterator Types. https://docs.python.org/3/library/stdtypes.html#iterator-types
2026
-
[16]
Rust Project Developers. 2026. Iterator Trait. https://doc.rust-lang.org/std/iter/trait.Iterator.html
2026
-
[17]
2011.The Boost C++ Libraries
Boris Schling. 2011.The Boost C++ Libraries. XML Press
2011
-
[18]
M. Steindorfer and J. Vinju. 2015. Optimizing hash-array mapped tries for fast and lean immutable JVM collections. In Object-Oriented Programming, Systems, Languages, and Applications. ACM. doi:10.1145/2814270.2814312
-
[19]
Stepanov and M
A. Stepanov and M. Lee. 1995.The Standard Template Library. Technical Report. Hewlett-Packard Laboratories
1995
-
[20]
N. Stucki, T. Rompf, V. Ureche, and P. Bagwell. 2015. RRB vector: a practical general purpose immutable sequence. In International Conference on Functional Programming. ACM. doi:10.1145/2784731.2784739
-
[21]
The Abseil Team. 2026. Abseil Common Libraries (C++). https://github.com/abseil/abseil-cpp
2026
-
[22]
The Catch2 Team. 2026. Catch2: A modern, C++-native, test framework for unit-tests, TDD and BDD. https: //github.com/catchorg/Catch2. Received 2025-11-14; accepted 2026-04-03 Proc. ACM Program. Lang., Vol. 10, No. PLDI, Article 246. Publication date: June 2026
2026
discussion (0)
Sign in with ORCID, Apple, or X to comment. Anyone can read and Pith papers without signing in.