[swift-evolution] Pitch: throwing sequences aka Cursor
Gwendal Roué
gwendal.roue at gmail.com
Tue Nov 29 16:37:33 CST 2016
Hello,
I'd like to discuss the opportunity to extend the Swift Standard Library with a new protocol and a family of concrete types.
The problem: Sequence and IteratorProtocol do not throw. They are unsuitable for external resources like database rows, file contents, socket bytes, etc. That's a pity, because the Standard Library provides a full suite of methods like map, flatMap, filter, first, reduce, etc that are both useful, and unavailable for I/O sequences.
This email provides the first draft for a new protocol, Cursor, and a family of reusable methods and concrete types that help handling untrustable sequences.
let cursor = /* Cursor of Int */
while let int = try cursor.next() {
print(int)
}
Ideally, the Swift compiler would provide sugar for Cursor, and let the user write:
// Handle errors in both cursor creation and iteration, in a single `for` statement
for try int in try makeCursor() {
print(int)
}
Cursor share traits from both LazySequenceProtocol and IteratorProtocol, but differs in several ways:
- Cursor types are classes, and have a lifetime. This is because Cursor aims at wrapping external resources, and has a non-mutating iteration method (because it is the external resource that mutates on iteration).
- Cursor iteration may throw errors.
- A cursor can not be repeated.
public protocol Cursor : class {
/// The type of element traversed by the cursor.
associatedtype Element
/// Advances to the next element and returns it, or nil if no next element
/// exists. Once nil has been returned, all subsequent calls return nil.
func next() throws -> Element?
}
Cursor can implement the classic contains(_:), contains(where:), enumerated(), first(where:), flatMap(ElementOfResult), flatMap(SequenceOfResult), flatMap(CursorOfResult), forEach(_:), joined(), map(_:), etc.
Like lazy sequence, Cursor.filter, map, flatMap, etc return other cursors.
One can derive an Array from a cursor, with try Array(cursor).
This is enough for a pitch, and grab your comments, if you find that Cursor would be a nice addition to the Standard Library.
There is already a working implementation of Cursor, that fuels the manipulation of database results in the next version of the GRDB.swift <https://github.com/groue/GRDB.swift/pull/148> library: see https://github.com/groue/GRDB.swift/blob/fc1fdab51a91dedc7f5233b32440f8e8411cdf0a/GRDB/Core/Cursor.swift <https://github.com/groue/GRDB.swift/blob/fc1fdab51a91dedc7f5233b32440f8e8411cdf0a/GRDB/Core/Cursor.swift>
Gwendal Roué
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161129/28ace27b/attachment.html>
More information about the swift-evolution
mailing list