scala 學習筆記-持續更新中

scala 學習筆記-持續更新中

學習列表:

  1. scala官方文檔
  2. scala cheat
  3. twitter Scala 課堂
  4. 有趣的 Scala 語言: 使用遞歸的方式去思考
  5. 《scala 編程》
  • 幾乎一切乎都是表達式

    scala> 1 + 1
    res0: Int = 2
  • 複合表達式——{}

    花括號用於創建複合表達式,複合表達式的返回值是最後一個表達式

    scala> {
       | println("hello world")
       | "hi"
       | }
    hello world
    res0: String = hi
  • 常量

    使用val,不能重複給常量賦值

    scala> val value = 100 + 1
    value: Int = 101
    scala> value = 200// 給常量重複賦值將報錯
    <console>:11: error: reassignment to val
         value = 200
               ^
  • 變量

    使用var,可以修改變量的值

    scala> var value = 100
    value: Int = 100
    scala> value = 200
    value: Int = 200
  • 類型推斷

    scala支持類型推斷,類型聲明置後,編譯器會推斷其類型,會比java更加簡潔

    scala> val m: Int = 100// 不建議
    m: Int = 100
    scala> var n: String = "hi"// 不建議
    n: String = hi
    scala> val m = 100// 推薦
    m: Int = 100
    scala> var n = "hi"// 推薦
    n: String = hi
  • 函數

    使用def創建函數(與python一樣),需要爲函數參數指定類型簽名,函數返回值類型可以不寫(遞歸函數必須聲明返回值類型),讓編譯器進行類型推斷

    scala> def sum(a: Int, b: Int): Int = a + b// 中規中矩的寫法
    sum: (a: Int, b: Int)Int
    scala> sum(2, 3)
    res8: Int = 5
    scala> def fun(x: Int) = x*x// 不聲明返回值類型
    fun: (x: Int)Int
    scala> fun(5)
    res9: Int = 25
    // 使用複合表達式
    scala> def mul(x: Int, y: Int) = {
       | println(x.toString)
       | println(y.toString)
       | x * y
       | }
    mul: (x: Int, y: Int)Int
    scala> mul(2, 3)
    2
    3
    res12: Int = 6
    // 無返回值的函數可以不用=,代表返回值爲Unit類似java中void
    scala> def hi() {
       | println("hi world!")
       | }
    hi: ()Unit
    scala> hi// 無參函數可以不使用括號調用
    hi world!
  • 匿名函數

    使用 =>

    scala> (x: Int) => x*x
    res14: Int => Int = <function1>
    scala> res14(5)
    res15: Int = 25

    可以將匿名函數進行賦值

    scala> val fun = (x: Int) => x*x
    fun: Int => Int = <function1>
    scala> fun(3)
    res27: Int = 9

    同樣可以使用{}定義複雜的匿名函數

    scala> var m = {x: Int =>
       | println("hi")
       | val temp = x*x
       | temp + 1
       | }
    m: Int => Int = <function1>
    scala> m(4)
    hi
    res28: Int = 17
  • 部分應用(partially applied function)

    你可以使用下劃線“_”(通配符)部分應用一個函數,結果將得到另一個函數。

    scala> def add(x: Int, y: Int) = x+y
    add: (x: Int, y: Int)Int
    scala> add(4, _:Int)
    res1: Int => Int = <function1>
    scala> res1(3)
    res2: Int = 7
  • 柯里化函數(curried)

    有時會有這樣的需求:允許別人一會在你的函數上應用一些參數,然後又應用另外的一些參數。

    scala> def mul(x: Int)(y:Int) = x*y
    mul: (x: Int)(y: Int)Int
    scala> mul(2)_
    res3: Int => Int = <function1>
    scala> res3(5)
    res4: Int = 10

    多參函數柯里化

    scala> def mul3(x: Int, y: Int, z: Int) = x*y*z
    mul3: (x: Int, y: Int, z: Int)Int
    scala> (mul3 _).curried
    res8: Int => (Int => (Int => Int)) = <function1>
    scala> res8(2)
    res9: Int => (Int => Int) = <function1>
    scala> res9(3)
    res10: Int => Int = <function1>
    scala> res10(4)
    res11: Int = 24
  • 變長參數

    向方法傳入任意多個同類型的參數,比如任意多個整數求和

    scala> def sum(nums: Int*) = (nums reduceLeft ((x: Int, y: Int) => x+y))
    sum: (nums: Int*)Int
    scala> sum(1,2,3,4,5,6,7,8,9,10)
    res19: Int = 55
  • 參數限定

    scala可以使用require進行函數參數限制,類似java assert

    scala> def sq(x: Int) = {
       | require(x >= 0, "input must > 0!")
       | math.sqrt(x)
       | }
    sq: (x: Int)Double
    scala> sq(2)
    res0: Double = 1.4142135623730951
    scala> sq(-1)
    java.lang.IllegalArgumentException: requirement failed: input must > 0!
    at scala.Predef$.require(Predef.scala:219)
    at .sq(<console>:11)
    ... 33 elided
  • 隱式類型轉換(implicit)

    在同一作用域下,自動進行類型的轉換,與該函數名無關,僅與其輸入輸出類型有關

    scala> implicit def fun(x: String) = x.toInt
    fun: (x: String)Int
    scala> math.max("132", 13)
    res0: Int = 132
  • 閉包(closure)

    函數及其執行所需的上下文環境(“An object is data with functions. A closure is a function with data.” — John D. Cook)

    scala> def fun() = {
       | var i = 0
       | val lam = () => {i+=1;i}
       | lam
       | }
    fun: ()() => Int
    scala> val clo = fun()
    clo: () => Int = <function0>
    scala> clo()
    res0: Int = 1
    scala> clo()
    res1: Int = 2
    scala> clo()
    res2: Int = 3
  • 傳名參數(call by name,傳值、傳引用之外的另外一種參數傳遞方式)

    傳名的參數傳遞使用替換規則。

    scala> def callByNameFun(x: => Int) = List(x, x)// =>開頭爲傳名參數
    callByNameFun: (x: => Int)List[Int]
    // 定義高階函數createNum產生一個函數,使用閉包,每調用一次fun(),i自增加1
    scala> def createNum() = {
       | var i = 0
       | val fun = {
       | () =>
       | i += 1
       | i
       | }
       | fun
       | }
    createNum: ()() => Int
    scala> val f = createNum()
    f: () => Int = <function0>
    scala> callByNameFun(f())
    res0: List[Int] = List(1, 2)
    scala> callByNameFun(f())
    res1: List[Int] = List(3, 4)
  • 尾遞歸

    尾遞歸函數返回值爲本身或者結果,同一般的遞歸相比,可被直接轉化爲循環,棧的開銷爲O(1),scala中可以用 @tailrec 檢測定義的函數是否爲尾遞歸

    scala> import scala.annotation.tailrec
    scala> @tailrec def fun(re: Int, index: Int): Int = {
       | if (index == 0) {
       | re
       | } else {
       | fun(re+index, index - 1)
       | }
       | }
    fun: (re: Int, index: Int)Int
    scala> fun(0, 100)
    res0: Int = 5050
    scala> fun(0, 100)
    res1: Int = 5050
  • 使用class關鍵字

    scala> class User {
       | var name = "bernie"
       | var age = 23
       | def show() = println(name + ":" + age.toString)
       | }
    defined class User
    scala> var user = new User()
    user: User = User@41112c13

    構造函數,構造函數不是特殊的方法,他們是除了類的方法定義之外的代碼。

    scala> class Person(pName: String, pAge: Int) {
       | var name = pName
       | var age = pAge
       | def show() = println(name + ":" + age.toString)
       | }
    defined class Person
    // 也可重載構造函數
    scala> class Person(pName: String, pAge: Int) {
       | def this(pName: String) = this(pName, 18)
       | var name = pName
       | var age = pAge
       | }
    defined class Person
  • 抽象類

    和java差不多,繼承也使用extends

    scala> abstract class AbstractFather {
       | def fun(x: Int): Int
       | }
    defined class AbstractFather
  • 特質(trait)

    是一組屬性與行爲的組合,特質可以多擴展,在抽象類與特質之間優先選擇特質

    scala> trait Fly {
       | val wing: Int
       | def fly() = println("I can fly")
       | }
    defined trait Fly
    scala> trait Run {
       | val leg: Int
       | def run() = println("I can run")
       | }
    defined trait Run
    scala> class Bird extends Fly with Run {
       | val wing = 2
       | val leg = 2
       | def power() = {
       | fly()
       | run()
       | }
       | }
    defined class Bird
    scala> new Bird().power()
    I can fly
    I can run
  • 單例的語言級別實現——object

    Util類就非常適合使用object定義

    object Util {
      def echo() = println("Hello World!")
    }
  • 伴生對象與伴生類

    名字相同的class與object,放在同一個文件下定義,能夠訪問彼此的私有成員

  • 泛型

    使用中括號,類和方法都可以是泛型的

    scala> class Gen[T] {
       | def show(x: T) = x.toString + "$"
       | }
    defined class Gen
    scala> val gen = new Gen[Int]
    gen: Gen[Int] = Gen@3a44ebcb
    scala> gen.show(100)
    res11: String = 100$
    scala> def genFun[T](x: T) = x.toString + "&"
    genFun: [T](x: T)String
    scala> genFun(100)
    res13: String = 100&
  • 語法糖 apply update

    爲了方便你使用類,scala提供了apply 與 update語法糖

    scala> object Arr {
       | val arr = Array(0,1,2,3,4,5)
       | def apply(i: Int) = arr(i)
       | def update(i: Int, value: Int) = {arr(i) = value}
       | }
    defined object Arr
    scala> Arr(1)
    res38: Int = 1
    scala> Arr(1) = 100
    scala> Arr.arr
    res40: Array[Int] = Array(0, 100, 2, 3, 4, 5)

    其實 Array 取值與更新就是實現了這兩個方法


    scala數組
  • 函數與對象de邊界

    函數可以看作一堆特性的集合(Funtion0 -> Funtion22),apply語法糖有助於統一對象和函數式編程的二重性,你可以傳遞類,並把它們當做函數使用,而函數本質上是類的實例

    scala> object Fun extends Function1[Int, Int] {
       | def apply(x: Int) = x*x
       | }
    defined object Fun
    scala> Fun(3)
    res50: Int = 9
  • 模式匹配

    感覺像java中switch case,但功能更加強大

    scala> val m = 1
    m: Int = 1
    scala> m match {
       | case 1 => 100
       | case 2 => 200
       | case _ => 300
       | }
    res25: Int = 100
  • 異常

    異常也是表達式

    scala> val re = try {
       | 1/0
       | "oh yeah"
       | } catch {
       | case e: Exception => println("error happen")
       | "oh no"
       | } finally {
       | println("turn me")
       | }
    error happen
    turn me
    re: String = oh no
  • 集合


    scala集合


    List(列表)、Set(集)、Tuple(元組)、Map(映射)、Option(選項)

    Tuple

    元組是在不使用類的前提下,將元素組合起來形成簡單的邏輯集合,讀取方式使用下標,從1開始,可以使用->創建2元組

    scala> val tuple = ("hi", "he", "ha", 12, 'a')
    tuple: (String, String, String, Int, Char) = (hi,he,ha,12,a)
    scala> tuple._1
    res36: String = hi
    scala> 1 -> 2
    res63: (Int, Int) = (1,2)

    Map

    scala> Map(1 -> "one", 2 -> "two")
    res0: scala.collection.immutable.Map[Int,String] = Map(1 -> one, 2 -> two)
    scala> Map((1, "one"), (2, "two"))
    res1: scala.collection.immutable.Map[Int,String] = Map(1 -> one, 2 -> two)

    Option

    表示可能包含值的容器,有Some與None兩個子類,特徵接口如下

    trait Option[T] {
    def isDefined: Boolean
    def get: T
    def getOrElse(t: T): T
    }
    scala> val map = Map(1 -> "one", 2 -> "two")
    map: scala.collection.immutable.Map[Int,String] = Map(1 -> one, 2 -> two)
    scala> map.get(1)
    res2: Option[String] = Some(one)
    scala> map.get(3)
    res3: Option[String] = None
    scala> res2.get
    res4: String = one
    scala> res3.get
    java.util.NoSuchElementException: None.get
    at scala.None$.get(Option.scala:347)
    at scala.None$.get(Option.scala:345)
    ... 33 elided
    scala> res3.isDefined
    res6: Boolean = false
    scala> res3.getOrElse("three")
    res7: String = three
  • 集合操作符(操作符即函數)

    map、foreach

    map將產生一個新的集合,foreach無返回值,一般僅作遍歷使用,取它的副作用

    scala> (1 to 10) map (_ * 2)
    res21: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
    scala> (1 to 10) foreach (println(_))
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    reduceLeft、reduceRight(將集合進行函數計算,得到結果)

    scala> (1 to 10) reduceLeft ((m: Int, n: Int) => m+n)
    res42: Int = 55
    scala> (1 to 10) reduceRight ((m: Int, n: Int) => m+n)
    res43: Int = 55

    filter(白名單過濾)、partition(分割)

    fliter將符合條件的元素產生一個集合返回,partition將其分隔成滿足與不滿足條件的兩元組

    scala> (1 to 10) filter (_%2 == 0)
    res24: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10)
    scala> (1 to 10) partition (_%2 == 0)
    res25: (scala.collection.immutable.IndexedSeq[Int], scala.collection.immutable.IndexedSeq[Int]) = (Vector(2, 4, 6, 8, 10),Vector(1, 3, 5, 7, 9))
    scala> res25._1
    res26: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10)
    scala> res25._2
    res27: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 3, 5, 7, 9)

    find、exists、count

    find返回符合條件的第一個選項 Option,exists返回Boolean值,count返回滿足條件的個數Int

    scala> (1 to 10) find (_%2==0)
    res30: Option[Int] = Some(2)
    scala> (1 to 10) exists (_%2==0)
    res50: Boolean = true
    scala> (1 to 10) count (_ %2 ==0)
    res57: Int = 5

    zip

    顧名思義就是像拉鍊一樣彼此咬合生成新的集合,長短不一的時候以短爲準

    scala> Array(1, 2, 3) zip List("a", "b", "c", "d")
    res53: Array[(Int, String)] = Array((1,a), (2,b), (3,c))
原文鏈接:http://www.jianshu.com/p/06808aed982b#
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章