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
—
Utilities for automatic resource management using the Using API, enabling safe handling of resources that need to be closed after use.
import scala.util.Usingobject Using {
def apply[R: Releasable, A](resource: => R)(f: R => A): Try[A]
object Manager {
def apply[A](f: Manager => A): Try[A]
}
}
trait Releasable[-R] {
def release(resource: R): Unit
}Automatically manages a single resource using Using.apply.
def apply[R: Releasable, A](resource: => R)(f: R => A): Try[A]Usage Example:
import java.io.{BufferedReader, FileReader}
import scala.util.{Try, Using}
val lines: Try[Seq[String]] =
Using(new BufferedReader(new FileReader("file.txt"))) { reader =>
Iterator.continually(reader.readLine()).takeWhile(_ != null).toSeq
}For managing multiple resources simultaneously, use Using.Manager.
object Manager {
def apply[A](f: Manager => A): Try[A]
trait Manager {
def apply[R: Releasable](resource: R): R
}
}Usage Example:
import java.io.{BufferedReader, FileReader}
import scala.util.{Try, Using}
val lines: Try[Seq[String]] = Using.Manager { use =>
val r1 = use(new BufferedReader(new FileReader("file1.txt")))
val r2 = use(new BufferedReader(new FileReader("file2.txt")))
val lines1 = Iterator.continually(r1.readLine()).takeWhile(_ != null).toSeq
val lines2 = Iterator.continually(r2.readLine()).takeWhile(_ != null).toSeq
lines1 ++ lines2
}The Releasable type class defines how resources should be released.
trait Releasable[-R] {
def release(resource: R): Unit
}Built-in Instances:
AutoCloseable (Java resources like streams, readers, writers)Custom Releasable Example:
case class DatabaseConnection(url: String) {
def close(): Unit = println(s"Closing connection to $url")
}
implicit val dbReleasable: Releasable[DatabaseConnection] =
(resource: DatabaseConnection) => resource.close()
val result: Try[String] = Using(DatabaseConnection("jdbc:...")) { conn =>
"Query result"
}The Using utilities wrap all operations in Try, providing safe error handling:
import java.io.FileInputStream
import scala.util.{Try, Success, Failure}
val result: Try[Int] = Using(new FileInputStream("data.txt")) { stream =>
stream.available()
}
result match {
case Success(size) => println(s"File size: $size bytes")
case Failure(exception) => println(s"Error: ${exception.getMessage}")
}When using Using.Manager, resources are released in reverse order of acquisition:
Using.Manager { use =>
val resource1 = use(openResource1()) // Released last
val resource2 = use(openResource2()) // Released second
val resource3 = use(openResource3()) // Released first
// ... use resources
}Note: The Using utility is only available in the Scala 2.11 compatibility version. In Scala 2.12+ and 2.13+, it's part of the standard library.
import java.io.{FileInputStream, FileOutputStream, BufferedInputStream, BufferedOutputStream}
import scala.util.{Try, Using}
def copyFile(source: String, dest: String): Try[Unit] = Using.Manager { use =>
val input = use(new BufferedInputStream(new FileInputStream(source)))
val output = use(new BufferedOutputStream(new FileOutputStream(dest)))
val buffer = new Array[Byte](8192)
var bytesRead = 0
while ({
bytesRead = input.read(buffer)
bytesRead != -1
}) {
output.write(buffer, 0, bytesRead)
}
output.flush()
}Install with Tessl CLI
npx tessl i tessl/maven-org-scala-lang-modules--scala-collection-compat