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/
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/