X In Y Minutes
Table of Contents
My take on the x in y minutes saga for Scala 2 (Also see the Scala language specification: https://www.scala-lang.org/files/archive/spec/2.13/).
First of all, the following are implicitly imported in every scala file:
import java.lang._ import scala._ import scala.Predef._
1. Naming
Note in Scala 2 val and defs cannot appear as toplevel definitions.
object Naming { // Ordinarily, we wouldn't need to provide the type of x here since it can // be determined via type inference, but here we voluntarily provide a // 'type ascription' val x: Int = 3 // Here Show is a Single Abstract Method (SAM) type trait Show[A] { def show(a: A): String } // Since Scala 2.12 function literals are accepted as valid SAM expressions: implicit val intShow: Show[Int] = n => s"here is my integer: $n" // A type alias type MyInt = Int // Beware, implicit classes and defs will still apply to Int! import scala.concurrent.duration._ implicit def myIntToDuration(n: MyInt): Duration = Duration(n, SECONDS) val myDuration: Duration = 3 }
2. Sorting
Also worth looking up are the notions of partial orderings, total orderings and well-orderings.
object Sorting { // Ordered is the equivalent to (and indeed extends) java's Comparable, ie it // represents 'natural' orderings case class DummyInt(x: Int) extends Ordered[DummyInt] { def compare(that: DummyInt): Int = x - that.x } // Similarly, Ordered is the equivalent to java's Comparator, note both are // available without import, as they are Members of the scala package case class DummyLong(x: Long) extends AnyVal // Ordering can be considered a contravariant functor, with 'on' providing the // equivalent of contramap implicit val dummyLongOrdering: Ordering[DummyLong] = Ordering[Long].on(dummyLong => dummyLong.x) val myList = List(DummyInt(10), DummyInt(1), DummyInt(-2), DummyInt(7)) println(myList.sorted) // List(DummyInt(x = -2), DummyInt(x = 1), DummyInt(x = 7), DummyInt(x = 10)) // Note the signature of sorted is sorted[B >: A](implicit ord: Ordering[B]) // but the companion of Ordered provides an implicit conversion from Ordered[A] // to Ordering[A] (https://www.scala-lang.org/api/current/scala/math/Ordered$.html) // An ordering on DummyLong induces an ordering on Seqs of DummyLongs // (the lexicographic ordering), we can obtain it via the import import scala.math.Ordering.Implicits._ // This import also brings into scope '<' (and others) to use with Orderings println(List(DummyLong(10)) < List(DummyLong(10), DummyLong(1))) // true }
3. Types
object Types { // A singleton type is a type which depends on a literal // See: https://docs.scala-lang.org/sips/42.type.html val lsSingle: List[1] = List(1, 1) // Let's introduce TypeTags! Consider the following: sealed trait BankBalance case class Savings(value: Int) extends BankBalance case class Debt(value: Int) extends BankBalance def check[A <: BankBalance](xs: List[A]) = xs match { case l: List[Debt] => s"Debts of size ${l.sum}!" case _: List[BankBalance] => "OK" } // The method above produces the compiler warning: // 'the type test for List[test.Debt] cannot be checked at runtime' // This is because of type erasure. // We can use TypeTags to fix this: import scala.reflect.runtime.universe._ def check2[A <: BankBalance : TypeTag](xs: List[A]) = typeOf[A] match { case t if t =:= typeOf[Debt] => s"Debts of size ${l.sum}!" case t if t <:< typeOf[BankBalance] => "OK" } }
4. Collections
object collections { // A standard Java array val a = Array(1, 2, 3) // Beware == on Array returns true iff the arrays point to the same reference a == Array(1, 2, 3) // false }