In [1]:
val pf1: PartialFunction[Any, String] = { case s: String => "YES" }
val pf2: PartialFunction[Any, String] = { case d: Double => "YES" }
val pf = pf1 orElse pf2
def tryPF(x: Any, f: PartialFunction[Any, String]): String = {
try {
f(x).toString
}
catch {
case _: MatchError => "ERROR!"
}
}
def d(x: Any, f: PartialFunction[Any, String]) =
f.isDefinedAt(x).toString
In [2]:
println(" | pf1 - String | pf2 - Double | pf - All")
println(" x | def? | pf1(x) | def? | pf2(x) | def? | pf(x)")
println("++++++++++++++++++++++++++++++++++++++++++++++++++++++")
List("str", 3.14, 10) foreach { x =>
printf("%-5s | %-5s | %-6s | %-5s | %-6s | %-5s | %-6s\n", x.toString,
d(x, pf1), tryPF(x, pf1), d(x, pf2), tryPF(x, pf2), d(x, pf), tryPF(x, pf))
}
In [3]:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
In [4]:
def sleep(millis: Long) = Thread.sleep(millis)
def doWork(index: Int) = {
sleep((math.random * 1000).toLong)
index
}
(1 to 5) foreach { index =>
val future = Future {
doWork(index)
}
future onSuccess {
case answer: Int => println(s"Success! returned: $answer")
}
future onFailure {
case th: Throwable => println(s"FAILURE! returned: $th")
}
}
sleep(1000)
println("Done")
上面代码中调用的三个方法中第二个参数列表具有隐含的ExecutionContext参数
//Future.apply
apply[T](body: => T)(implicit executor: ExecutionContext): Future[T]
def onSuccess[U](func: (Try[T]) => U)(implicit executor: ExecutionContext): Unit
def onFailure[U](callback: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Unit
Future通过ExecutionContext来配置并发操作的执行,默认情况使用Java的ForkJoinPool来设置管理Java线程池。
In [5]:
import scala.annotation.tailrec
def factorial(i: Int): Long = {
@tailrec
def fact(i: Int, accumulator: Int): Long = {
if (i <= 1) accumulator
else fact(i-1, i*accumulator)
}
fact(i, 1)
}
(0 to 5) foreach (i => println(factorial(i)))
In [6]:
// 不是尾递归的情况,编译器将抛出错误
@tailrec
def f(i: Int): Long = {
if(i <= 1) 1L
else f(i-2) + f(i-1)
}
显式类型注解的场景:
Option允许我们通过Some和None显式表示“有值”或“没有值”,通过类型检查避免空指针异常(null)的情况。
In [7]:
val stateCapitals = Map(
"Alabama" -> "Montgomery",
"Alaska" -> "Juneau",
"Wyoming" -> "Cheyenne"
)
In [8]:
println("Get the capitals wrapped in Options:")
println("Alabama: " + stateCapitals.get("Alabama"))
println("Wyoming: " + stateCapitals.get("Wyoming"))
println("Unknown: " + stateCapitals .get("Unknown"))
println("Get the capitals themselves out of Options:")
println("Alabama: " + stateCapitals.get("Alabama").get)
println("Wyoming: " + stateCapitals.get("Wyoming").getOrElse("Oops!"))
println("Unknown: " + stateCapitals .get("Unknown").getOrElse("Oops!"))
Map.get方法返回了Option[T],对于给定的key,当对应的值可能并不存在的情况,Option已经包含在方法返回的类型中了。
Option有get或getOrElse方法,其中None.get会抛出一个NoSuchElementException异常。更安全的方法是使用getOrElse,其参数起到默认值的作用,避免潜在的异常。
In [9]:
import java.io._
abstract class BulkReader[In] {
val source: In
def read: String
}
class StringBulkReader(val source: String) extends BulkReader[String] {
def read: String = source
}
class FileBulkReader(val source: File) extends BulkReader[File] {
def read: String = {
val in = new BufferedInputStream(new FileInputStream(source))
val numBytes = in.available()
val bytes = new Array[Byte](numBytes)
in.read(bytes, 0, numBytes)
new String(bytes)
}
}
In [10]:
println(new StringBulkReader("Hello Scala!").read)
println(new FileBulkReader(new File("fileBulkReaderTestFile.txt")).read)