Scalable 编程语言特点(可伸缩的,既可以编写小脚本,又可以写服务端的大程序)
- 纯正的面向对象语言
- 函数式语言
- 无缝的Java互操作(建立在jvm基础上的)
SBT:Simple Build Tools
REPL:Read Evaluate Print Loop(交互式编程)(读取-求值-打印-循环)
启动REPL的两种方式:
- 在cmd下输入scala
- (安装sbt后)在cmd下输入sbt console
开发scala的IDE
- The Scala IDE(basee on Eclipse) http://scala-ide.org/
- IntelliJ IDEA with Scala plugin
- Netbeans IDE with the Scala plugin
变量(三种变量修饰符)
- val 定义immutable variable(常量)
- var 定义mutable variable(变量)
- lazy val(惰性求值的常量)
可以不显示指定变量的类型,因为Scala会自动进行类型推导
Byte(1个字节)/Short(2个字节)/Int(4个字节)/Long(8个字节)/Float/Double
Block(块)
{exp1;exp2}
{
exp1
exp2
}
Block也是一个表达式,其最终的求得的值是最后一个表达式的值
函数
def funcionName(param:ParamType):ReturnType = {
//function body:expressions
}
if表达式
if(logical_exp) valA else valB
if(true) 1 else 2
if表达式也是有返回值的,这一点不同于java
for表达式
for{
x<- s
y = x+1
if(y>0)
}yield y
try表达式
try{}
catch{}
finally{}
try{
Integer.parseInt("dog")
} catch{
case _ => 0 //下划线通配所有对象
}finally{
println("always be printed")
}
match表达式
//主要用在pattern match中
exp match{
case p1 => val1
case p2 => val2
...
case _ => valn
}
code match{
case 1 => "one"
case 2 => "two"
case _ => "others"
}
求值策略:
Scala里有两种求值策略(Evaluation Strategy)
1.Call By Value - 对参数实参求值,且仅求值一次
2.Call By Name - 参数实参每次在函数体内被用到时都会求值
Scala通常使用Call By Value
如果函数形参类型以 => 开头,那么会使用Call By Name
def foo(x: Int) = x //call by value
def foo(x: => Int) = x //call by name
举例:
def bar(x: Int,y: => Int):Int = 1
def loop():Int = loop //这是一个递归,死循环
下面两次调用bar:
bar(1,loop) //返回1
bar(loop,1) //一直进行死循环,不返回
函数是第一等公民
Scala语言支持:
- 把函数作为实参传递给另外一个函数
- 把函数作为返回值
- 把函数赋值给变量
- 把函数存储在数据结构里
即在Scala中,函数就像普通变量一样,同样也具有函数的类型
函数类型
在Scala语言中,函数类型的格式为A => B,表示一个接受类型A的参数,并返回类型B的函数
例子:Int => String 是把整形映射为字符串的函数类型
高阶函数
用函数作为形参或返回值的函数,称为高阶函数
def operate(f:(Int,Int) => Int) = {
f(4,4)
}
def greeting() = (name: String) => {"Hello"+" "+name} //这是一个匿名函数
匿名函数
匿名函数(Anonymous Function),就是函数常量,也称为函数文字量(Function Literal)
在Scala里,匿名函数的定义格式为:
(形参列表) => {函数体}
柯里化
柯里化函数(Curried Function)把具有多个参数的函数转换为一条函数链,每个节点上是单一参数。
例子:以下两个add函数定义是等价的
def add(x: Int,y: Int) = x + y
def add(x: Int)(y: Int) = x + y //Scala里柯里化的语法
例子:
def curriedAdd(a: Int)(b: Int) = a + b
curriedAdd(2)(2) // 4
val addOne = curriedAdd(1)_ //Int => Int
addOne(2) //3
递归函数
递归函数(Recursive Function)在函数式编程中是实现循环的一种技术
例子:计算n!
def factorial(n: Int) : Int ={
if(n <= 0) 1
else n * factorial(n - 1)
}
递归的天生缺陷就是效率低,递归到深处容易堆栈异常,所以要对递归进行优化------>尾递归函数
尾递归函数(Tail Recursive Function)中所有递归形式的调用都出现在函数的末尾
当编译器检测到一个函数调用是尾递归的时候,它就覆盖当前的活动记录而不是在栈中去创建一个新的。
@annotation.tailrec //告诉scala编译器对下面这个函数进行递归优化,不加此注解,scala编译器是不会主动去优化的
def factorial(n: Int,m: Int): Int =
if(n <= 0) m
else factorial(n - 1,m * n)
调用:
factorial(5,1)
List
常用操作:
- ::
- :::
- head
- tail
- isEmpty
-
filter: 接收一个返回true/false的函数
val a : List[Int] = List(1,2,3)
a.filter(x => x % 2 ==1)
"99 Red Balloons".toList得到List[Char] = List(9,9 ,R,e,d, ,B,a,l,l,o,o,n,s)
"99 Red Balloons".toList.filter(x=>Character.isDigit(x))返回List[Char] = List(9,9) -
takeWhile:也是接收一个返回true/false的函数
"99 Red Balloons".toList.takeWhile(x=>x!='B')返回List[Char]=List(9,9, ,R,e,d, )
到'B'那的时候得到false就终止了 -
map:接收一个映射的函数
val c = List(x,y,z)
c.map(x=>x.toUpperCase)返回List[String] = List(X,Y,Z)
这里有一个简写方式就是""通配,即c.map(.toUpperCase)
同样上边的filter也可以简写为a.filter(%2==1)
可以连续使用:a.filter( % 2 == 1).map( _ + 10)得到List[Int] = LIst(11,13)
val q = List(List(1,2,3),List(4,5,6))
q.map(x=>x.filter(%2==0))返回List(List(2),List(4,6))
也可以简写为q.map(.filter(_%2==0)) -
flatMap:
上边的q可以q.flatMap(.filter(%2==0))得到List(2,4,6) -
reduceLeft:归约操作
val a = List(1,2,3)
a.reduceLeft((x,y)=>x+y)返回6
简写为a.reduceLeft(_ + _)返回6 -
foldLeft:
a.foldLeft(0)(_ + )返回6
a.foldLeft(1)( * _)返回6
Range:
1 to 10 得到Range(1,2,3,4,5,6,7,8,9,10)
1 to 10 by 2得到Range(1,3,5,7,9),其中2代表步长为2
(1 to 10).toList得到List(1,2,3,4,5,6,7,8,9,10)
1 until 10得到(1,2,3,4,5,6,7,8,9)
Stream:Stream is a lazy List
1 #:: 2 #::3 #:: Stream.empty得到Stream(1,?)
val stream = (1 to 100000000).toStream得到Stream(1,?)
类似List:
stream.head stream.tail 等
Tuple:元组
(1,2)
1 -> 2
(1,"Alice","Math",95.5)
访问元素:t._1,t._3
def sumSq(in:List[Int]):(Int,Int,Int)=in.foldLeft((0,0,0))((t,v)=>(t._1+1,t._2+v,t._3+v*v))
Map:
val p = Map(1 -> "David",9 -> "Elwood")
p(1)得到David
p.contains(1)返回true
p.keys得到Set(1,9)
p.values得到MapLike(David,Elwood)
p + (8 -> "Archer")
p - 1
p ++ List(2 -> "Alice",5 -> "Bob")
p -- List(1,9,2)
scala递归实现排序,代码特别简单:
def qSort(a:List[Int]):List[Int]=
if(a.length<2) a
else qSort(a.filter(_<a.head)) ++ a.filter(_ == a.head) ++ qSort(a.filter(_ > a.head))