scala(九)A Tour of Scala: Compound Types

scala(9)A Tour of Scala: Compound Types
scala(9)A Tour of Scala: Compound Types
Compound Types
trait Cloneable extends java.lang.Cloneable {
     override def clone(): Cloneable = { super.clone(); this }
}

trait Resetable {
     def reset: Unit
}

def cloneAndReset(obj: Cloneable with Resetable): Cloneable = {
     //...
}

Sequence Comprehensions
object ComprehensionTest1 extends App {
     def even(from: Int, to: Int): List[Int] =
          for (i <- List.range(from, to) if i % 2 == 0) yieldi
     Console.println(even(0, 20)) // List(0, 2, 4, 6, 8, 10, 12, 14, 16, 18)
}

object ComprehensionTest2 extends App {
  def foo(n: Int, v: Int) =
    for (i <- 0 until n;
         j <- i + 1 until n if i + j == v) yield
      Pair(i, j);
  foo(20, 32) foreach {
    case (i, j) =>
      println("(" + i + ", " + j + ")")
  }
}

Another easy way to implement this.

object ComprehensionTest3 extends App {
  for (i <- Iterator.range(0, 20);
       j <- Iterator.range(i + 1, 20) if i + j == 32)
  println("(" + i + ", " + j + ")")
}

Extractor Objects

object Twice{
  def apply(x:Int): Int = x * 2
  def unapply(z: Int): Option[Int] = if (z%2 == 0) Some(z/2) else None
}

object TwiceTest extends App{
     valx = Twice(21)
     println("apply value: " + x)    //apply value: 42
     xmatch { case Twice(n) => Console.println("unapply value: " + n) } //unapply value: 21
}

There are 2 syntactic conventions at work here:
1. case Twice(n) will cause an invocation of Twice.unapplly
2. val x = Twice(21) expands to val x = Twice.apply(21).

Generic Classes
class Stack[T] {
     var elems: List[T] = Nil
     def push(x: T) { elems = x::elems }
     def top: T = elems.head
     def pop() { elems = elems.tail }
}

Here is the parameterized with types classes, like in Java 5.

object GenericsTest extends App {
  val stack = new Stack[Int]
  stack.push(1)
  stack.push('a')
  println(stack.top) // 97
  stack.pop()
  println(stack.top) // 1
}

Implicit Parameters(Implicit in Scala)
There are 2 implicit in Scala, implicit transfer and implicit parameters.

implicit transfer
scala> def foo(msg: String) = println(msg)
foo: (msg: String)Unit

scala> foo(5)
<console>:9: error: type mismatch;
found : Int(5)
required: String
              foo(5)
                  ^

scala> implicit def intToString(x: Int) = x.toString
warning: there were 1 feature warnings; re-run with -feature for details
intToString: (x: Int)String

scala> foo(5)
5

But if we have 2 implicit transfer, it will give us some error messages:
Note that implicit conversions are not applicable because they are ambiguous:
both method int2String of type (x: Int)String
and method int2String2 of type (x: Int)String
are possible conversion functions from Int(5) to String
              foo(5)

implicit Parameters
cala> def findAnInt(implicit x : Int) = x
findAnInt: (implicit x: Int)Int

scala> findAnInt
<console>:9: error: could not find implicit value for parameter x: Int
              findAnInt
              ^

scala> implicit val test = 100
test: Int = 100

scala> findAnInt
res1: Int = 100

References:
http://www.scala-lang.org/node/110
http://www.scala-lang.org/node/112
http://www.scala-lang.org/node/114

http://www.zhangyf.net/2012/11/implicit-in-scala/