A library that makes some Scala 2.13 APIs available on Scala 2.11 and 2.12, facilitating cross-building Scala 2.13 and 3.0 code on older versions
—
Scala 2.13 collection types made available on Scala 2.11 and 2.12, enabling forward compatibility for code that targets multiple Scala versions.
A lazy, immutable linked list that evaluates elements only when needed. LazyList is the replacement for Stream in Scala 2.13+.
final class LazyList[+A] private (private[this] var lazyState: () => LazyList.State[A])
extends AbstractSeq[A] with LinearSeq[A] with LinearSeqOptimized[A, LazyList[A]] {
def head: A
def tail: LazyList[A]
def isEmpty: Boolean
def force: this.type
def knownSize: Int
}def head: A
def tail: LazyList[A]Access the first element and remaining elements. Elements are computed lazily.
Usage:
val lazyList = LazyList(1, 2, 3, 4, 5)
val first = lazyList.head // 1
val rest = lazyList.tail // LazyList(2, 3, 4, 5)def isEmpty: BooleanCheck if the lazy list is empty.
def force: this.typeForce evaluation of all elements in the lazy list. Detects and handles cycles.
Usage:
val infinite = LazyList.from(1)
// infinite.force // Would not terminate
val finite = LazyList(1, 2, 3).force // Forces evaluation of all elementsdef knownSize: IntReturns the known size without forcing evaluation, or -1 if unknown.
object LazyList extends SeqFactory[LazyList] {
def empty[A]: LazyList[A]
def apply[A](elems: A*): LazyList[A]
def from[A](coll: GenTraversableOnce[A]): LazyList[A]
def iterate[A](start: => A)(f: A => A): LazyList[A]
def continually[A](elem: => A): LazyList[A]
def unfold[A, S](init: S)(f: S => Option[(A, S)]): LazyList[A]
def concat[A](xss: collection.Iterable[A]*): LazyList[A]
def from(start: Int): LazyList[Int]
def from(start: Int, step: Int): LazyList[Int]
def fill[A](n: Int)(elem: => A): LazyList[A]
def tabulate[A](n: Int)(f: Int => A): LazyList[A]
}def from[A](coll: GenTraversableOnce[A]): LazyList[A]
def from(start: Int): LazyList[Int]
def from(start: Int, step: Int): LazyList[Int]Create a LazyList from a collection or generate an infinite sequence of integers.
Usage:
LazyList.from(List(1, 2, 3)) // LazyList(1, 2, 3)
LazyList.from(1) // LazyList(1, 2, 3, 4, ...)
LazyList.from(0, 2) // LazyList(0, 2, 4, 6, ...)def iterate[A](start: => A)(f: A => A): LazyList[A]Create an infinite LazyList by repeatedly applying a function.
Usage:
LazyList.iterate(1)(_ * 2) // LazyList(1, 2, 4, 8, 16, ...)
LazyList.iterate("a")(_ + "a") // LazyList("a", "aa", "aaa", ...)def continually[A](elem: => A): LazyList[A]Create an infinite LazyList with the same element repeated.
Usage:
LazyList.continually(42) // LazyList(42, 42, 42, ...)
LazyList.continually(scala.util.Random.nextInt()) // Random numbersdef unfold[A, S](init: S)(f: S => Option[(A, S)]): LazyList[A]Create a LazyList by unfolding a state with a generating function.
Usage:
// Generate Fibonacci sequence
LazyList.unfold((0, 1)) { case (a, b) =>
Some((a, (b, a + b)))
} // LazyList(0, 1, 1, 2, 3, 5, 8, ...)
// Generate sequence up to a limit
LazyList.unfold(0) { n =>
if (n < 10) Some((n, n + 1)) else None
} // LazyList(0, 1, 2, ..., 9)def fill[A](n: Int)(elem: => A): LazyList[A]
def tabulate[A](n: Int)(f: Int => A): LazyList[A]Create finite LazyLists with repeated elements or computed elements.
Usage:
LazyList.fill(5)("x") // LazyList("x", "x", "x", "x", "x")
LazyList.tabulate(5)(n => n * n) // LazyList(0, 1, 4, 9, 16)object cons {
def apply[A](hd: => A, tl: => LazyList[A]): LazyList[A]
def unapply[A](xs: LazyList[A]): Option[(A, LazyList[A])]
}Alternative construction and pattern matching for LazyList.
object #:: {
def unapply[A](s: LazyList[A]): Option[(A, LazyList[A])]
}
implicit def toDeferrer[A](l: => LazyList[A]): Deferrer[A]
final class Deferrer[A] private[LazyList] (private val l: () => LazyList[A]) {
def #::[B >: A](elem: => B): LazyList[B]
def #:::[B >: A](prefix: LazyList[B]): LazyList[B]
}Lazy cons operators for constructing LazyLists.
Usage:
val lazyList = 1 #:: 2 #:: 3 #:: LazyList.empty
val infinite = 1 #:: infinite.map(_ + 1)
// Pattern matching
lazyList match {
case head #:: tail => println(s"Head: $head, Tail: $tail")
case _ => println("Empty")
}An immutable sequence backed by an array, providing efficient indexed access with a small memory footprint.
abstract class ArraySeq[+T] extends AbstractSeq[T] with IndexedSeq[T]
with IndexedSeqOptimized[T, ArraySeq[T]] {
def length: Int
def apply(index: Int): T
def unsafeArray: Array[T]
def clone(): ArraySeq[T]
}def length: Int
def apply(index: Int): TStandard indexed sequence operations with O(1) access time.
def unsafeArray: Array[T]Direct access to the underlying array. Use with caution as it breaks immutability guarantees if modified.
def clone(): ArraySeq[T]Create a deep copy of the ArraySeq, including cloning the underlying array.
object ArraySeq {
def empty[T <: AnyRef]: ArraySeq[T]
def apply[T](elems: T*)(implicit elemTag: ClassTag[T]): ArraySeq[T]
def unsafeWrapArray[T](x: Array[T]): ArraySeq[T]
def newBuilder[T](implicit elemTag: ClassTag[T]): Builder[T, ArraySeq[T]]
def unapplySeq[T](seq: ArraySeq[T]): Some[ArraySeq[T]]
}def apply[T](elems: T*)(implicit elemTag: ClassTag[T]): ArraySeq[T]Create an ArraySeq from variable arguments.
Usage:
ArraySeq(1, 2, 3, 4, 5) // ArraySeq[Int]
ArraySeq("a", "b", "c") // ArraySeq[String]def unsafeWrapArray[T](x: Array[T]): ArraySeq[T]Wrap an existing array in an ArraySeq without copying. The array should not be modified after wrapping.
Usage:
val array = Array(1, 2, 3, 4, 5)
val arraySeq = ArraySeq.unsafeWrapArray(array)def empty[T <: AnyRef]: ArraySeq[T]Create an empty ArraySeq.
ArraySeq provides specialized implementations for primitive types to avoid boxing:
final class ofRef[T <: AnyRef](val unsafeArray: Array[T]) extends ArraySeq[T]
final class ofInt(val unsafeArray: Array[Int]) extends ArraySeq[Int]
final class ofDouble(val unsafeArray: Array[Double]) extends ArraySeq[Double]
final class ofLong(val unsafeArray: Array[Long]) extends ArraySeq[Long]
final class ofFloat(val unsafeArray: Array[Float]) extends ArraySeq[Float]
final class ofChar(val unsafeArray: Array[Char]) extends ArraySeq[Char]
final class ofByte(val unsafeArray: Array[Byte]) extends ArraySeq[Byte]
final class ofShort(val unsafeArray: Array[Short]) extends ArraySeq[Short]
final class ofBoolean(val unsafeArray: Array[Boolean]) extends ArraySeq[Boolean]
final class ofUnit(val unsafeArray: Array[Unit]) extends ArraySeq[Unit]import scala.collection.compat.immutable._
// Fibonacci sequence
val fibs: LazyList[BigInt] = BigInt(0) #:: BigInt(1) #::
fibs.zip(fibs.tail).map { case (a, b) => a + b }
fibs.take(10).foreach(println) // Print first 10 Fibonacci numbers
// Prime numbers using sieve
def sieve(s: LazyList[Int]): LazyList[Int] =
s.head #:: sieve(s.tail.filter(_ % s.head != 0))
val primes = sieve(LazyList.from(2))
primes.take(10).toList // List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29)// Expensive computation with memoization
def expensiveCompute(n: Int): Int = {
Thread.sleep(100) // Simulate expensive operation
n * n
}
val lazyResults = LazyList.tabulate(10)(expensiveCompute)
// Only computed when accessed
val firstFew = lazyResults.take(3).toListimport scala.collection.compat.immutable._
val seq = ArraySeq(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// O(1) access
val element = seq(5) // 6
val length = seq.length // 10
// Efficient operations
val doubled = seq.map(_ * 2)
val filtered = seq.filter(_ % 2 == 0)// Specialized for primitives - no boxing
val intSeq = ArraySeq(1, 2, 3, 4, 5) // ArraySeq.ofInt
val doubleSeq = ArraySeq(1.0, 2.0, 3.0) // ArraySeq.ofDouble
val boolSeq = ArraySeq(true, false, true) // ArraySeq.ofBoolean
// Wrap existing arrays
val array = Array(10, 20, 30, 40, 50)
val wrapped = ArraySeq.unsafeWrapArray(array)LazyList replaces Stream in Scala 2.13+ArraySeq provides an immutable alternative to Vector with different performance characteristicsInstall with Tessl CLI
npx tessl i tessl/maven-org-scala-lang-modules--scala-collection-compat