scala基础内容-杂项
特殊之处
In Scala assignment always results in the unit value, ()
var a = 1
(a = 2).getClass //=> Class[Unit] = void
读取文件
import scala.io.Source
if(args.length > 0){
for(line <- Source.fromFile(args(0)).getLines())
println(line.length + " " + line)
}
else{
Console.err.println("Please enter filename")
}
Closures
def inc(more: Int) = (x: Int) => x + more
val inc1 = inc(1)
val inc100 = inc(100)
Special function call forms
Repeated parameters
def echo(args: String*) =
for (arg <- args) println(arg)
echo: (args: String*)Unit
echo("first", "second")
val arr = Array("What's", "up", "doc?")
echo(arr: _*)
Named arguments
def speed(distance: Float, time: Float): Float =
distance/time
speed(time = 10, distance = 100) // diff in invoking
Default parameter values
def printTime(out: java.io.PrintStream = Console.out) =
out.println("time = " + System.currentTimeMillis())
def printTime2(out: java.io.PrintStream = Console.out, divisor: Int = 1) =
out.println("time = " + System.currentTimeMillis()/divisor)
printTime2(out = Console.err)
printTime2(divisor = 1000)
High-order function
def filesMatching(matcher: String => Boolean) =
for(file <- filesHere; if matcher(file.getName))
yield file
def filesEnding(query: String) =
filesMatching(_.endsWith(query))
Case
for 语句中的模式
模式在 for 语句中也非常重要。 所有能在值定义的左侧使用的模式都适用于 for 语句的值定义。 因此,如果我们有一个球员得分集,想确定谁能进名人堂(得分超过一定上限), 用 for 语句就可以解决:
for中隐含着case。
def gameResults(): Seq[(String, Int)] =
("Daniel", 3500) :: ("Melissa", 13000) :: ("John", 7000) :: Nil
def hallOfFame = for {
result <- gameResults()
(name, score) = result
if (score > 5000)
} yield name
模式匹配与匿名函数
val wordFrequencies = ("habitual", 6) :: ("and", 56) :: ("consuetudinary", 2) ::
("additionally", 27) :: ("homely", 5) :: ("society", 13) :: Nil
wordFrequencies.filter(wf => wf._2 > 3 && wf._2 < 25).map(_._1)
// => List(habitual, homely, society)
changed to: wordFrequencies.filter{case (_, i) => i > 3 && i < 25}.map{case (n, _) => n}
if we use:
wordFrequencies.filter(case (_, i) => i > 30)
error: illegal start of simple expression // error !!!
PartialFunction
val pf = new PartialFunction[(String, Int), String] {
def apply(wordFrequency: (String, Int)) = wordFrequency match {
case (word, freq) if freq > 3 && freq < 25 => word
}
def isDefinedAt(wordFrequency: (String, Int)) = wordFrequency match {
case (word, freq) if freq > 3 && freq < 25 => true
case _ => false
}
}
wordFrequencies.map(pf) // will throw a MatchError
wordFrequencies.collect(pf) // right
类型 Option
Option[A] 是一个类型为 A 的可选值的容器: 如果值存在, Option[A] 就是一个 Some[A] ,如果不存在, Option[A] 就是对象 None 。
在类型层面上指出一个值是否存在,使用你的代码的开发者(也包括你自己)就会被编译器强制去处理这种可能性, 而不能依赖值存在的偶然性。
Option 是强制的!不要使用 null 来表示一个值是缺失的。
The most idiomatic way to use an scala.Option instance is to treat it as a collection or monad and use map,flatMap, filter, or foreach.
val greeting: Option[String] = Some("Hello world")
val greeting: Option[String] = None
在实际工作中,你不可避免的要去操作一些 Java 库, 或者是其他将 null 作为缺失值的JVM 语言的代码。 为此, Option 伴生对象提供了一个工厂方法,可以根据给定的参数创建相应的 Option :
val absentGreeting: Option[String] = Option(null) // absentGreeting will be None
val presentGreeting: Option[String] = Option("Hello!") // presentGreeting will be Some("Hello!")
case class User(
id: Int,
firstName: String,
lastName: String,
age: Int,
gender: Option[String]
)
val user = User(2, "Johanna", "Doe", 30, None)
println("Gender: " + user.gender.getOrElse("not specified")) // will print "not specified"
val user = User(2, "Johanna", "Doe", 30, None)
user.gender match {
case Some(gender) => println("Gender: " + gender)
case None => println("Gender: not specified")
}
Try 与错误处理
Try 的语义
Option[A] 是一个可能有值也可能没值的容器, Try[A] 则表示一种计算: 这种计算在成功的情况下,返回类型为 A 的值,在出错的情况下,返回 Throwable 。 这种可以容纳错误的容器可以很轻易的在并发执行的程序之间传递。
Try 有两个子类型:
Success[A]:代表成功的计算。- 封装了
Throwable的Failure[A]:代表出了错的计算。
import scala.util.Try
import java.net.URL
def parseURL(url: String): Try[URL] = Try(new URL(url))
flatMap将最后生成的嵌套值进行flat(多见于Option, Try)。
Option[Option[String]] => Option[String]
Catching exceptions and finally clause
import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException
try {
val f = new FileReader("input.txt")
} catch {
case ex: FileNotfoundexception => //
case ex: IOException => //
} finally {
f.close()
}
既然 Try 支持 flatMap 、 map 、 filter ,能够使用 for 语句也是理所当然的事情, 而且这种情况下的代码更可读。
import scala.io.Source
def getURLContent(url: String): Try[Iterator[String]] =
for {
url <- parseURL(url)
connection <- Try(url.openConnection())
is <- Try(connection.getInputStream)
source = Source.fromInputStream(is)
} yield source.getLines()
浙公网安备 33010602011771号