Cursor

interface Cursor<T>

An immutable, persistent, singly-linked view over a (possibly lazily produced) sequence of elements of type T, akin to a Lisp-style (head . tail) cons cell.

A Cursor differs from Kotlin's Iterator in two important ways: it is immutable (advancing to next yields a new Cursor, leaving the original one untouched and still usable), and it can be shared/reused from multiple call sites without any of them interfering with the others' traversal position. This makes it a good building block for lazily-constructed, structurally-shared data (e.g. Prolog lists, see it.unibo.tuprolog.core.List.from(Cursor, Term?) in the :core module, which wraps a Cursor of Terms without eagerly materializing them), where a plain Iterator would be unsuitable because it can only be consumed once and does not support branching.

Use Cursor.of (or the toCursor/cursor extension functions) to obtain a Cursor out of an Iterator, Iterable, Sequence, Array or Collection; use Cursor.empty to get the canonical empty cursor. A finished cursor (i.e. one for which isOver is true) has no current element and calling next on it throws.

var cursor: Cursor<out T> = listOf(1, 2, 3).cursor()
while (!cursor.isOver) {
println(cursor.current)
cursor = cursor.next
}

Type Parameters

T

is the type of the elements traversed by this cursor

Types

Link copied to clipboard
object Companion

Properties

Link copied to clipboard
abstract val current: T?

The element this cursor currently points at, or null if this cursor isOver.

Link copied to clipboard
abstract val hasNext: Boolean

Whether this cursor still has, at least, one more element to yield after current (i.e. whether next is not isOver). Always false once the cursor isOver.

Link copied to clipboard
abstract val isLazy: Boolean

Whether this cursor lazily pulls elements from an underlying Iterator (as, e.g., the ones created via Cursor.of or toCursor) rather than exposing an already fully-computed chain.

Link copied to clipboard
abstract val isOver: Boolean

Whether this cursor has been fully traversed, i.e. it has no current element left to yield.

Link copied to clipboard
abstract val next: Cursor<out T>

The cursor pointing to the element following current, or, if this cursor isOver, a cursor that is also isOver.

Functions

Link copied to clipboard
open fun asIterable(): Iterable<T>

Returns an Iterable view of this cursor; each call to Iterable.iterator yields a fresh traversal starting again from current.

Link copied to clipboard
open fun asSequence(): Sequence<T>

Returns a Sequence view of this cursor, equivalent to asIterable().asSequence().

Link copied to clipboard
abstract fun iterator(): Iterator<T>

Returns a (one-shot) Iterator traversing the elements of this cursor, from current onwards.

Link copied to clipboard
abstract fun <R> map(mapper: (T) -> R): Cursor<out R>

Lazily transforms every element yielded by this cursor via mapper, returning a new cursor of the mapped elements. The returned cursor mirrors the laziness of the original one: mapper is invoked on each element only when it is actually traversed.

Link copied to clipboard
operator fun <T> Cursor<out T>.plus(other: Cursor<out T>): Cursor<out T>

Concatenates this cursor with other, yielding a Cursor that traverses first the elements of this cursor, then, once it Cursor.isOver, the elements of other.