第1章——探索Scala

Scala 是一门强大的编程语言:不需要牺牲强大的静态类型检查支持,就可以写出富有表 现力而又简洁的代码。

1.2 以少胜多

Introduction/TopStock.scala

val symbols = List("AMD", "AAPL", "AMZN", "IBM", "ORCL", "MSFT")
val year = 2017

val (topStock, topPrice) =
  symbols
    .map { ticker =>
      (ticker, getYearEndClosingPrice(ticker, year))
    }
    .maxBy { stockPrice =>
      stockPrice._2
    }

printf(s"Top stock of $year is $topStock closing at price $$$topPrice")

Introduction/TopStock.scala

case class Record(year: Int, month: Int, date: Int, closePrice: BigDecimal)

def getYearEndClosingPrice(symbol: String, year: Int): BigDecimal = {
  val url = s"https://raw.githubusercontent.com/ReactivePlatform/" +
    s"Pragmatic-Scala-StaticResources/master/src/main/resources/" +
    s"stocks/daily/daily_$symbol.csv"

  val data = io.Source.fromURL(url).mkString
  val maxClosePrize = data
    .split("\n")
    .filter(record => record.startsWith(s"$year-12"))
    .map(record => {
      val Array(timestamp, open, high, low, close, volume) = record.split(",")
      val Array(year, month, date) = timestamp.split("-")
      Record(year.toInt, month.toInt, date.toInt, BigDecimal(close.trim))
    })
    .sortBy(_.date)(Ordering[Int].reverse)
    .take(1)
    .map(_.closePrice)
    .head
  maxClosePrize
}

运行结果

Top stock of 2017 is AMZN closing at price $1169.4700

Introduction/FastTopStock.scala

import scala.collection.parallel.CollectionConverters._
val (topStock, topPrice) =
  symbols.par
    .map { ticker =>
      (ticker, getYearEndClosingPrice(ticker, year))
    }
    .maxBy { stockPrice =>
      stockPrice._2
    }

编译sample.scala的结果

sample.scala:2:
error: type mismatch;
 found   : String("haha")
 required: Int
i = "haha" //Error
    ^
one error found

1.3 函数式编程

Introduction/FindMax.java

 public static int findMax(List<Integer> temperatures) {
     //Java code
  int highTemperature = Integer.MIN_VALUE;
  for(int temperature : temperatures) {
   highTemperature = Math.max(highTemperature, temperature);
  }
  return highTemperature;
}

Introduction/FindMaxImperative.scala

def findMax(temperatures: List[Int]) = {
  var highTemperature = Integer.MIN_VALUE
  for (temperature <- temperatures) {
    highTemperature = Math.max(highTemperature, temperature)
  }
  highTemperature
}

Introduction/FindMaxFunctional.scala

def findMax(temperatures: List[Int]) = {
  temperatures.foldLeft(Integer.MIN_VALUE) { Math.max }
}

Introduction/ScalaDoubleValues.scala

val values = List(1, 2, 3, 4, 5)

val doubleValues = values.map(_ * 2)