Givens and Using Clauses
Contextual abstractions let the compiler pass values for you. A
given defines a value available in a context; a using parameter asks
for one.
case class Config(currency: String, taxRate: Double)
def priceWithTax(net: Double)(using config: Config): String =
f"${net * (1 + config.taxRate)}%.2f ${config.currency}"
def invoiceLine(item: String, net: Double)(using Config): String =
s"$item: ${priceWithTax(net)}"
@main def givens(): Unit =
given Config = Config("EUR", 0.2)
println(invoiceLine("Keyboard", 89))
println(invoiceLine("Monitor", 249.99))
println(priceWithTax(100)(using Config("GBP", 0.0)))
Keyboard: 106.80 EUR
Monitor: 299.99 EUR
100.00 GBP
(using config: Config)— the compiler fills this parameter with agiven Configin scope.invoiceLinepasses it on implicitly: its ownusing Configis in scope when it callspriceWithTax. The configuration flows through the call chain without being repeated at every call.- You can still pass a value explicitly with
(using ...).
Where the compiler looks
The compiler finds givens in the current scope (including imports) and
in the companion objects of the types involved. Givens are imported
explicitly with import Module.given, so it's always clear where they
come from.
object Formats:
given Ordering[String] = Ordering.by(_.length)
@main def importingGivens(): Unit =
val words = List("banana", "fig", "cherry", "kiwi")
println(words.sorted)
import Formats.given
println(words.sorted)
List(banana, cherry, fig, kiwi)
List(fig, kiwi, banana, cherry)
sorted takes a using Ordering[A]. The default Ordering[String] is
alphabetical; after importing the given from Formats, the local one wins
and words are sorted by length.
Good uses
- Type class instances (next lesson) — by far the most common use.
- Context that many functions need: an execution context, a configuration, a database transaction.
Avoid givens for ordinary values like Int or String — the more
specific the type, the safer implicit passing is.
(Scala 2 used implicit val and implicit parameters for the same
ideas — you'll see them in older code and libraries.)