99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

Scala

2018-02-24 15:18 更新

X分鐘速成Y

其中 Y=Scala

源代碼下載:?learnscala-zh.scala

Scala - 一門可拓展的語言

/*
  自行設(shè)置:

  1) 下載 Scala - http://www.scala-lang.org/downloads
  2) unzip/untar 到您喜歡的地方,并把 bin 子目錄添加到 path 環(huán)境變量
  3) 在終端輸入 scala,啟動 Scala 的 REPL,您會看到提示符:

  scala>

  這就是所謂的 REPL (讀取-求值-輸出循環(huán),英語: Read-Eval-Print Loop),
  您可以在其中輸入合法的表達式,結(jié)果會被打印。
  在教程中我們會進一步解釋 Scala 文件是怎樣的,但現(xiàn)在先了解一點基礎(chǔ)。
*/

/////////////////////////////////////////////////
// 1\. 基礎(chǔ)
/////////////////////////////////////////////////

//  單行注釋開始于兩個斜杠

/*
  多行注釋,如您之前所見,看起來像這樣
*/

// 打印并強制換行
println("Hello world!")
println(10)

// 沒有強制換行的打印
print("Hello world")

// 通過 var 或者 val 來聲明變量
// val 聲明是不可變的,var 聲明是可修改的。不可變性是好事。
val x = 10 // x 現(xiàn)在是 10
x = 20 // 錯誤: 對 val 聲明的變量重新賦值
var y = 10 
y = 20  // y 現(xiàn)在是 20

/*
  Scala 是靜態(tài)語言,但注意上面的聲明方式,我們沒有指定類型。
  這是因為類型推導(dǎo)的語言特性。大多數(shù)情況, Scala 編譯器可以推測變量的類型,
  所以您不需要每次都輸入??梢韵襁@樣明確聲明變量類型:
*/
val z: Int = 10
val a: Double = 1.0

// 注意從 Int 到 Double 的自動轉(zhuǎn)型,結(jié)果是 10.0, 不是 10
val b: Double = 10

// 布爾值
true
false

// 布爾操作
!true // false
!false // true
true == false // false
10 > 5 // true

// 數(shù)學(xué)運算像平常一樣
1 + 1 // 2
2 - 1 // 1
5 * 3 // 15
6 / 2 // 3
6 / 4 // 1
6.0 / 4 // 1.5

// 在 REPL 計算一個表達式會返回給您結(jié)果的類型和值

1 + 7

/* 上行的結(jié)果是:

  scala> 1 + 7
  res29: Int = 8

  這意味著計算 1 + 7 的結(jié)果是一個 Int 類型的對象,其值為 8

  注意 "res29" 是一個連續(xù)生成的變量名,用以存儲您輸入的表達式結(jié)果,
  您看到的輸出可能不一樣。
*/

"Scala strings are surrounded by double quotes"
'a' // Scala 的字符
// '不存在單引號字符串' <= 這會導(dǎo)致錯誤

// String 有常見的 Java 字符串方法
"hello world".length
"hello world".substring(2, 6)
"hello world".replace("C", "3")

// 也有一些額外的 Scala 方法,另請參見:scala.collection.immutable.StringOps
"hello world".take(5)
"hello world".drop(5)

// 字符串改寫:留意前綴 "s"
val n = 45
s"We have $n apples" // => "We have 45 apples"

// 在要改寫的字符串中使用表達式也是可以的
val a = Array(11, 9, 6)
s"My second daughter is ${a(0) - a(2)} years old." // => "My second daughter is 5 years old."
s"We have double the amount of ${n / 2.0} in apples." // => "We have double the amount of 22.5 in apples."
s"Power of 2: ${math.pow(2, 2)}" // => "Power of 2: 4"

// 添加 "f" 前綴對要改寫的字符串進行格式化
f"Power of 5: ${math.pow(5, 2)}%1.0f" // "Power of 5: 25"
f"Square root of 122: ${math.sqrt(122)}%1.4f" // "Square root of 122: 11.0454"

// 未處理的字符串,忽略特殊字符。
raw"New line feed: \n. Carriage return: \r." // => "New line feed: \n. Carriage return: \r."

// 一些字符需要轉(zhuǎn)義,比如字符串中的雙引號
"They stood outside the \"Rose and Crown\"" // => "They stood outside the "Rose and Crown""

// 三個雙引號可以使字符串跨越多行,并包含引號
val html = """<form id="daform">
                <p>Press belo', Joe</p>
                <input type="submit">
              </form>"""

/////////////////////////////////////////////////
// 2\. 函數(shù)
/////////////////////////////////////////////////

// 函數(shù)可以這樣定義:
//
//   def functionName(args...): ReturnType = { body... }
//
// 如果您以前學(xué)習(xí)過傳統(tǒng)的編程語言,注意 return 關(guān)鍵字的省略。
// 在 Scala 中, 函數(shù)代碼塊最后一條表達式就是返回值。
def sumOfSquares(x: Int, y: Int): Int = {
  val x2 = x * x
  val y2 = y * y
  x2 + y2
}

// 如果函數(shù)體是單行表達式,{ } 可以省略:
def sumOfSquaresShort(x: Int, y: Int): Int = x * x + y * y

// 函數(shù)調(diào)用的語法是熟知的:
sumOfSquares(3, 4)  // => 25

// 在多數(shù)情況下 (遞歸函數(shù)是需要注意的例外), 函數(shù)返回值可以省略,
// 變量所用的類型推導(dǎo)一樣會應(yīng)用到函數(shù)返回值中:
def sq(x: Int) = x * x  // 編譯器會推斷得知返回值是 Int

// 函數(shù)可以有默認(rèn)參數(shù)
def addWithDefault(x: Int, y: Int = 5) = x + y
addWithDefault(1, 2)  // => 3
addWithDefault(1)  // => 6

// 匿名函數(shù)是這樣的:
(x:Int) => x * x

// 和 def 不同,如果語義清晰,匿名函數(shù)的參數(shù)類型也可以省略。
// 類型 "Int => Int" 意味著這個函數(shù)接收一個 Int 并返回一個 Int。
val sq: Int => Int = x => x * x

// 匿名函數(shù)的調(diào)用也是類似的:
sq(10)   // => 100

// 如果您的匿名函數(shù)中每個參數(shù)僅使用一次,
// Scala 提供一個更簡潔的方式來定義他們。這樣的匿名函數(shù)極為常見,
// 在數(shù)據(jù)結(jié)構(gòu)部分會明顯可見。
val addOne: Int => Int = _ + 1
val weirdSum: (Int, Int) => Int = (_ * 2 + _ * 3)

addOne(5)  // => 6
weirdSum(2, 4)  // => 16

// return 關(guān)鍵字是存在的,但它只從最里面包裹了 return 的 def 函數(shù)中返回。
// 警告: 在 Scala 中使用 return 容易出錯,應(yīng)該避免使用。
// 在匿名函數(shù)中沒有效果,例如:
def foo(x: Int): Int = {
  val anonFunc: Int => Int = { z =>
    if (z > 5)
      return z  // 這一行令 z 成為 foo 函數(shù)的返回值!
    else
      z + 2  // 這一行是 anonFunc 函數(shù)的返回值
  }
  anonFunc(x)  // 這一行是 foo 函數(shù)的返回值
}

/*
 * 譯者注:此處是指匿名函數(shù)中的 return z 成為最后執(zhí)行的語句,
 *    在 anonFunc(x) 下面的表達式(假設(shè)存在)不再執(zhí)行。如果 anonFunc
 *    是用 def 定義的函數(shù), return z 僅返回到 anonFunc(x) ,
 *    在 anonFunc(x) 下面的表達式(假設(shè)存在)會繼續(xù)執(zhí)行。
 */

/////////////////////////////////////////////////
// 3\. 控制語句
/////////////////////////////////////////////////

1 to 5
val r = 1 to 5
r.foreach( println )

r foreach println
// 附注: Scala 對點和括號的要求想當(dāng)寬松,注意其規(guī)則是不同的。
// 這有助于寫出讀起來像英語的 DSL(領(lǐng)域特定語言) 和 API(應(yīng)用編程接口)。

(5 to 1 by -1) foreach ( println )

// while 循環(huán)
var i = 0
while (i < 10) {  println("i " + i); i+=1  }

while (i < 10) {  println("i " + i); i+=1  }   // 沒錯,再執(zhí)行一次,發(fā)生了什么?為什么?

i    // 顯示 i 的值。注意 while 是經(jīng)典的循環(huán)方式,它連續(xù)執(zhí)行并改變循環(huán)中的變量。
     // while 執(zhí)行很快,比 Java 的循環(huán)快,但像上面所看到的那樣用組合子和推導(dǎo)式
     // 更易于理解和并行化。

// do while 循環(huán)
do {
  println("x is still less than 10");
  x += 1
} while (x < 10)

// Scala 中尾遞歸是一種符合語言習(xí)慣的遞歸方式。
// 遞歸函數(shù)需要清晰的返回類型,編譯器不能推斷得知。
// 這是一個 Unit。
def showNumbersInRange(a:Int, b:Int):Unit = {
  print(a)
  if (a < b)
    showNumbersInRange(a + 1, b)
}
showNumbersInRange(1,14)

// 條件語句

val x = 10

if (x == 1) println("yeah")
if (x == 10) println("yeah")
if (x == 11) println("yeah")
if (x == 11) println ("yeah") else println("nay")

println(if (x == 10) "yeah" else "nope")
val text = if (x == 10) "yeah" else "nope"

/////////////////////////////////////////////////
// 4\. 數(shù)據(jù)結(jié)構(gòu)
/////////////////////////////////////////////////

val a = Array(1, 2, 3, 5, 8, 13)
a(0)
a(3)
a(21)    // 拋出異常

val m = Map("fork" -> "tenedor", "spoon" -> "cuchara", "knife" -> "cuchillo")
m("fork")
m("spoon")
m("bottle")       // 拋出異常

val safeM = m.withDefaultValue("no lo se")
safeM("bottle")

val s = Set(1, 3, 7)
s(0)
s(1)

/* 這里查看 map 的文檔 -
 * http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Map
 * 并確保你會閱讀
 */

// 元組

(1, 2)

(4, 3, 2)

(1, 2, "three")

(a, 2, "three")

// 為什么有這個?
val divideInts = (x:Int, y:Int) => (x / y, x % y)

divideInts(10,3) // 函數(shù) divideInts 同時返回結(jié)果和余數(shù)

// 要讀取元組的元素,使用 _._n,n是從1開始的元素索引
val d = divideInts(10,3)

d._1

d._2

/////////////////////////////////////////////////
// 5\. 面向?qū)ο缶幊?/////////////////////////////////////////////////

/*
  旁白: 教程中到現(xiàn)在為止我們所做的一切只是簡單的表達式(值,函數(shù)等)。
  這些表達式可以輸入到命令行解釋器中作為快速測試,但它們不能獨立存在于 Scala 
  文件。舉個例子,您不能在 Scala 文件上簡單的寫上 "val x = 5"。相反 Scala 文件
  允許的頂級結(jié)構(gòu)是:

  - objects
  - classes
  - case classes
  - traits

  現(xiàn)在來解釋這些是什么。
*/

// 類和其他語言的類相似,構(gòu)造器參數(shù)在類名后聲明,初始化在類結(jié)構(gòu)體中完成。
class Dog(br: String) {
  // 構(gòu)造器代碼在此
  var breed: String = br

  // 定義名為 bark 的方法,返回字符串
  def bark = "Woof, woof!"

  // 值和方法作用域假定為 public。"protected" 和 "private" 關(guān)鍵字也是可用的。
  private def sleep(hours: Int) =
    println(s"I'm sleeping for $hours hours")

  // 抽象方法是沒有方法體的方法。如果取消下面那行注釋,Dog 類必須被聲明為 abstract
  //   abstract class Dog(...) { ... }
  // def chaseAfter(what: String): String
}

val mydog = new Dog("greyhound")
println(mydog.breed) // => "greyhound"
println(mydog.bark) // => "Woof, woof!"

// "object" 關(guān)鍵字創(chuàng)造一種類型和該類型的單例。
// Scala 的 class 常常也含有一個 “伴生對象”,class 中包含每個實例的行為,所有實例
// 共用的行為則放入 object 中。兩者的區(qū)別和其他語言中類方法和靜態(tài)方法類似。
// 請注意 object 和 class 可以同名。
object Dog {
  def allKnownBreeds = List("pitbull", "shepherd", "retriever")
  def createDog(breed: String) = new Dog(breed)
}

// Case 類是有額外內(nèi)建功能的類。Scala 初學(xué)者常遇到的問題之一便是何時用類
// 和何時用 case 類。界線比較模糊,但通常類傾向于封裝,多態(tài)和行為。類中的值
// 的作用域一般為 private , 只有方向是暴露的。case 類的主要目的是放置不可變
// 數(shù)據(jù)。它們通常只有幾個方法,且方法幾乎沒有副作用。
case class Person(name: String, phoneNumber: String)

// 創(chuàng)造新實例,注意 case 類不需要使用 "new" 關(guān)鍵字
val george = Person("George", "1234")
val kate = Person("Kate", "4567")

// 使用 case 類,您可以輕松得到一些功能,像 getters:
george.phoneNumber  // => "1234"

// 每個字段的相等性比較(無需覆蓋 .equals)
Person("George", "1234") == Person("Kate", "1236")  // => false

// 簡單的拷貝方式
// otherGeorge == Person("george", "9876")
val otherGeorge = george.copy(phoneNumber = "9876")

// 還有很多。case 類同時可以用于模式匹配,接下來會看到。

// 敬請期待 Traits !

/////////////////////////////////////////////////
// 6\. 模式匹配
/////////////////////////////////////////////////

// 模式匹配是一個強大和常用的 Scala 特性。這是用模式匹配一個 case 類的例子。
// 附注:不像其他語言, Scala 的 case 不需要 break, 其他語言中 switch 語句的
// fall-through 現(xiàn)象不會發(fā)生。

def matchPerson(person: Person): String = person match {
  // Then you specify the patterns:
  case Person("George", number) => "We found George! His number is " + number
  case Person("Kate", number) => "We found Kate! Her number is " + number
  case Person(name, number) => "We matched someone : " + name + ", phone : " + number
}

val email = "(.*)@(.*)".r  // 定義下一個例子會用到的正則

// 模式匹配看起來和 C語言家族的 switch 語句相似,但更為強大。
// Scala 中您可以匹配很多東西:
def matchEverything(obj: Any): String = obj match {
  // 匹配值:
  case "Hello world" => "Got the string Hello world"

  // 匹配類型:
  case x: Double => "Got a Double: " + x

  // 匹配時指定條件
  case x: Int if x > 10000 => "Got a pretty big number!"

  // 像之前一樣匹配 case 類:
  case Person(name, number) => s"Got contact info for $name!"

  // 匹配正則表達式:
  case email(name, domain) => s"Got email address $name@$domain"

  // 匹配元組:
  case (a: Int, b: Double, c: String) => s"Got a tuple: $a, $b, $c"

  // 匹配數(shù)據(jù)結(jié)構(gòu):
  case List(1, b, c) => s"Got a list with three elements and starts with 1: 1, $b, $c"

  // 模式可以嵌套
  case List(List((1, 2,"YAY"))) => "Got a list of list of tuple"
}

// 事實上,你可以對任何有 "unapply" 方法的對象進行模式匹配。
// 這個特性如此強大以致于 Scala 允許定義一個函數(shù)作為模式匹配:
val patternFunc: Person => String = {
  case Person("George", number) => s"George's number: $number"
  case Person(name, number) => s"Random person's number: $number"
}

/////////////////////////////////////////////////
// 7\. 函數(shù)式編程
/////////////////////////////////////////////////

// Scala 允許方法和函數(shù)作為其他方法和函數(shù)的參數(shù)和返回值。

val add10: Int => Int = _ + 10 // 一個接受一個 Int 類型參數(shù)并返回一個 Int 類型值的函數(shù)
List(1, 2, 3) map add10 // List(11, 12, 13) - add10 被應(yīng)用到每一個元素

// 匿名函數(shù)可以被使用來代替有命名的函數(shù):
List(1, 2, 3) map (x => x + 10)

// 如果匿名函數(shù)只有一個參數(shù)可以用下劃線作為變量
List(1, 2, 3) map (_ + 10)

// 如果您所應(yīng)用的匿名塊和匿名函數(shù)都接受一個參數(shù),那么你甚至可以省略下劃線
List("Dom", "Bob", "Natalia") foreach println

// 組合子

// 譯注: val sq: Int => Int = x => x * x
s.map(sq)

val sSquared = s. map(sq)

sSquared.filter(_ < 10)

sSquared.reduce (_+_)

// filter 函數(shù)接受一個 predicate (函數(shù)根據(jù)條件 A 返回 Boolean)并選擇
// 所有滿足 predicate 的元素
List(1, 2, 3) filter (_ > 2) // List(3)
case class Person(name:String, age:Int)
List(
  Person(name = "Dom", age = 23),
  Person(name = "Bob", age = 30)
).filter(_.age > 25) // List(Person("Bob", 30))

// Scala 的 foreach 方法定義在某些集合中,接受一個函數(shù)并返回 Unit (void 方法)
// 另請參見:
// http://www.scala-lang.org/api/current/index.html#scala.collection.IterableLike@foreach(f:A=>Unit):Unit
val aListOfNumbers = List(1, 2, 3, 4, 10, 20, 100)
aListOfNumbers foreach (x => println(x))
aListOfNumbers foreach println

// For 推導(dǎo)式

for { n <- s } yield sq(n)

val nSquared2 = for { n <- s } yield sq(n)

for { n <- nSquared2 if n < 10 } yield n

for { n <- s; nSquared = n * n if nSquared < 10} yield nSquared

/* 注意,這些不是 for 循環(huán),for 循環(huán)的語義是‘重復(fù)’,然而 for 推導(dǎo)式定義
   兩個數(shù)據(jù)集合的關(guān)系。 */

/////////////////////////////////////////////////
// 8\. 隱式轉(zhuǎn)換
/////////////////////////////////////////////////

/* 警告 警告: 隱式轉(zhuǎn)換是 Scala 中一套強大的特性,因此容易被濫用。
 * Scala 初學(xué)者在理解它們的工作原理和最佳實踐之前,應(yīng)抵制使用它的誘惑。
 * 我們加入這一章節(jié)僅因為它們在 Scala 的庫中太過常見,導(dǎo)致沒有用隱式轉(zhuǎn)換的庫
 * 就不可能做有意義的事情。這章節(jié)主要讓你理解和使用隱式轉(zhuǎn)換,而不是自己聲明。
 */

// 可以通過 "implicit" 聲明任何值(val, 函數(shù),對象等)為隱式值,
// 請注意這些例子中,我們用到第5部分的 Dog 類。
implicit val myImplicitInt = 100
implicit def myImplicitFunction(breed: String) = new Dog("Golden " + breed)

// implicit 關(guān)鍵字本身不改變值的行為,所以上面的值可以照常使用。
myImplicitInt + 2  // => 102
myImplicitFunction("Pitbull").breed  // => "Golden Pitbull"

// 區(qū)別在于,當(dāng)另一段代碼“需要”隱式值時,這些值現(xiàn)在有資格作為隱式值。
// 一種情況是隱式函數(shù)參數(shù)。
def sendGreetings(toWhom: String)(implicit howMany: Int) =
  s"Hello $toWhom, $howMany blessings to you and yours!"

// 如果提供值給 “howMany”,函數(shù)正常運行
sendGreetings("John")(1000)  // => "Hello John, 1000 blessings to you and yours!"

// 如果省略隱式參數(shù),會傳一個和參數(shù)類型相同的隱式值,
// 在這個例子中, 是 “myImplicitInt":
sendGreetings("Jane")  // => "Hello Jane, 100 blessings to you and yours!"

// 隱式的函數(shù)參數(shù)使我們可以模擬其他函數(shù)式語言的 type 類(type classes)。
// 它經(jīng)常被用到所以有特定的簡寫。這兩行代碼是一樣的:
def foo[T](implicit c: C[T]) = ...
def foo[T : C] = ...

// 編譯器尋找隱式值另一種情況是你調(diào)用方法時
//   obj.method(...)
// 但 "obj" 沒有一個名為 "method" 的方法。這樣的話,如果有一個參數(shù)類型為 A
// 返回值類型為 B 的隱式轉(zhuǎn)換,obj 的類型是 A,B 有一個方法叫 "method" ,這樣
// 轉(zhuǎn)換就會被應(yīng)用。所以作用域里有上面的 myImplicitFunction, 我們可以這樣做:
"Retriever".breed  // => "Golden Retriever"
"Sheperd".bark  // => "Woof, woof!"

// 這里字符串先被上面的函數(shù)轉(zhuǎn)換為 Dog 對象,然后調(diào)用相應(yīng)的方法。
// 這是相當(dāng)強大的特性,但再次提醒,請勿輕率使用。
// 事實上,當(dāng)你定義上面的隱式函數(shù)時,編譯器會作出警告,除非你真的了解
// 你正在做什么否則不要使用。

/////////////////////////////////////////////////
// 9\. 雜項
/////////////////////////////////////////////////

// 導(dǎo)入類
import scala.collection.immutable.List

// 導(dǎo)入所有子包
import scala.collection.immutable._

// 一條語句導(dǎo)入多個類
import scala.collection.immutable.{List, Map}

// 使用 ‘=>’ 對導(dǎo)入進行重命名
import scala.collection.immutable.{ List => ImmutableList }

// 導(dǎo)入所有類,排除其中一些。下面的語句排除了 Map 和 Set:
import scala.collection.immutable.{Map => _, Set => _, _}

// 在 Scala 文件用 object 和單一的 main 方法定義程序入口:
object Application {
  def main(args: Array[String]): Unit = {
    // stuff goes here.
  }
}

// 文件可以包含多個 class 和 object,用 scalac 編譯源文件

// 輸入和輸出

// 按行讀文件
import scala.io.Source
for(line <- Source.fromFile("myfile.txt").getLines())
  println(line)

// 用 Java 的 PrintWriter 寫文件
val writer = new PrintWriter("myfile.txt")
writer.write("Writing line for line" + util.Properties.lineSeparator)
writer.write("Another line here" + util.Properties.lineSeparator)
writer.close()

更多的資源

為沒耐心的人準(zhǔn)備的 Scala

Twitter Scala school

The Scala documentation

在瀏覽器嘗試 Scala

加入?Scala 用戶組

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號