pf1 orElse pf2 orElse pf3 ...
。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
pf1: PartialFunction[Any, String] = <function1> pf2: PartialFunction[Any, String] = <function1> pf: PartialFunction[Any, String] = <function1> defined function tryPF defined function d
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))
}
| pf1 - String | pf2 - Double | pf - All
x | def? | pf1(x) | def? | pf2(x) | def? | pf(x) ++++++++++++++++++++++++++++++++++++++++++++++++++++++ str | true | YES | false | ERROR! | true | YES 3.14 | false | ERROR! | true | YES | true | YES 10 | false | ERROR! | false | ERROR! | false | ERROR!
scala.concurrent.Future是scala提供的并发工具,但任务封装在Future中执行时,该任务是异步的
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future import scala.concurrent.ExecutionContext.Implicits.global
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")
Success! returned: 2 Success! returned: 3 Success! returned: 1 Success! returned: 4 Done
defined function sleep defined function doWork
上面代码中调用的三个方法中第二个参数列表具有隐含的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线程池。
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)))
1 1 2 6 24 120
import scala.annotation.tailrec defined function factorial
// 不是尾递归的情况,编译器将抛出错误
@tailrec
def f(i: Int): Long = {
if(i <= 1) 1L
else f(i-2) + f(i-1)
}
Compilation Failed
Main.scala:81: could not optimize @tailrec annotated method f: it is neither private nor final so can be overridden
def f(i: Int): Long = {
^
显式类型注解的场景:
Option允许我们通过Some和None显式表示“有值”或“没有值”,通过类型检查避免空指针异常(null)的情况。
val stateCapitals = Map(
"Alabama" -> "Montgomery",
"Alaska" -> "Juneau",
"Wyoming" -> "Cheyenne"
)
stateCapitals: Map[String, String] = Map( "Alabama" -> "Montgomery", "Alaska" -> "Juneau", "Wyoming" -> "Cheyenne" )
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!"))
Get the capitals wrapped in Options: Alabama: Some(Montgomery) Wyoming: Some(Cheyenne) Unknown: None Get the capitals themselves out of Options: Alabama: Montgomery Wyoming: Cheyenne Unknown: Oops!
Map.get方法返回了Option[T],对于给定的key,当对应的值可能并不存在的情况,Option已经包含在方法返回的类型中了。
Option有get或getOrElse方法,其中None.get会抛出一个NoSuchElementException异常。更安全的方法是使用getOrElse,其参数起到默认值的作用,避免潜在的异常。
Scala使用方括号表示参数化类型,并通过+、-号表示协类型和逆类型。
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)
}
}
import java.io._ defined class BulkReader defined class StringBulkReader defined class FileBulkReader
println(new StringBulkReader("Hello Scala!").read)
println(new FileBulkReader(new File("fileBulkReaderTestFile.txt")).read)
Hello Scala! this is a file for read method of FileBulkReader class do some work