[scala]學習筆記一
一、scala的特點:
1.Scalable程式語言 (可伸縮的,既可以是指令碼語言,又可以為大型伺服器所使用)
2.純正的面向物件的語言
3.函式式語言
4.無縫的Java互操作
二、scala函式式的程式設計思想:
1.純函式,不具有副作用
2.引用透明
3.函式是一等公民:一切都是計算,函數語言程式設計中只有表示式和變數!函式也是表示式
三、變數
1.val:定義常量(immutable variable),同java的final,給值後就不能再改變
2.var:定義變數(mutable variable),可以改變賦值的內容
3.lazy val:定義的時候不求值,在第一次使用的時候才會求值,即第一次操作時才會延遲載入
建議使用val
scala> lazy val a=1
a: Int = <lazy>
scala> a
res0: Int = 1
四、資料型別
1.數值型別:Byte、Short、Int、Long、Float、Double
2.布林型別:true、false
3.字元型別:Char
4.Unit型別:函式無返回值時,定義為Unit型別
5.Nothing和None
6.String:構建於Java的String之上,新增了字串插值的特性
scala> val string="Nina" string: String = Nina scala> s"my name is ${string}" res1: String = my name is Nina
五、函式
函式/方法的定義:
//主函式 def main(args: Array[String]): Unit = { println(add(3,4)) println(three()) println(three) //函式沒有形參的話,可以直接呼叫函式名,不需要加小括號 hello() } def add(x:Int,y:Int):Int={ x+y } def three()=1+2 //方法體只有一行,不需要加大括號 def hello(): Unit ={ //Unit表示函式沒有返回值 println("hello world") }
六、引數
1.預設引數:在函式定義時,允許指定引數的預設值
def main(args: Array[String]): Unit = {
sayName() //不指定引數呼叫
sayName("Jack")) //指定引數呼叫
}
def sayName(name:String="Nina"): Unit ={ //預設引數是Nina
println("hello, "+name)
}
結果:
hello, Nina
hello, Jack
2.命名引數:可以更改某一函式中引數的位置,但需要指明該函式的名稱,不太建議
3.可變引數:引數的個數可以改變
def main(args: Array[String]): Unit = {
println(sum(1,2)) //可變引數,函式中引數的個數不同,都可以呼叫sun()函式進行計算
println(sum(1,2,3,4))
}
def sum(numbers:Int*)={ //Int後的*用來匹配可變的引數值
var result:Int=0
for(number:Int<-numbers){
result+=number
}
result
}
結果:
3
10
七、if表示式、for表示式、try表示式、match表示式
1.if表示式
scala> val x=1
x: Int = 1
scala> if (x>0) true else false
res2: Boolean = true
2.for表示式
val arr=Array("Nina","Jack","Linda") //定義了一個Array
arr.foreach(name=>println(name)) //迴圈打印出arr中內容的一種方法
for(name<- arr) //迴圈打印出arr中內容的另一種方法
println(name)
3.try表示式:try()、catch()、finally()
try{
Integer.parseInt("dog")
}catch{
case _ =>0
}finally{
println("always be printed")
}
結果:
always be printed
res3: Int = 0
4.match表示式:同Java中的switch
scala> x match{
case 1 =>"one"
case 2=>"two"
case 3=>"three"
case _=>"default"
}
結果:
res4: String = two
八、求值策略
1.call by value:def foo(x:Int)=x
2.call by name:def foo(x:=>Int)=x
call by value 會對函式的形參先求值
//call by value
def foo(x:Int,y:Int)=x*x
結果:foo(3+4,8)->foo(7,8)->7*7->49
//call by name
def foo(x:=>Int,y:=>Int)=x*x
結果:foo(3+4,8)->(3+4)*(3+4)->7*(3+4)->7*7->49
九、柯里化
把具有多個引數的函式轉換成一條函式鏈,每個節點上是單一引數
//普通
def add(x:Int,y:Int)=x+y
//柯里化語法
def add(x:Int)(y:Int)=x+y
十、遞迴函式
在函數語言程式設計中沒有迴圈,需要通過遞迴來實現迴圈
遞迴會使用到棧,容易溢位,因此改進推出了尾遞迴函式
尾遞迴函式:
尾遞迴函式中所有遞迴形式的呼叫都出現在函式的末尾
當編譯器檢測到一個函式的呼叫是尾遞迴時,它就覆蓋當前的活動記錄,而不是在棧中建立一個新的,從而避免了棧溢位的問題
scala> @annotation.tailrec //宣告是尾遞迴
def fac(n:Int,m:Int):Int={ //m用於記錄結果,不停的被覆蓋
if(n==1) m
else fac(n-1,m*n)
}
結果:
scala> fac(5,1)
res4: Int = 120