Scala
其中Unit表示AnyVal中的空值而Null表示AnyRef中的空值。Scala中的绝大部分内容都和其他语言类似,差距比较大的是三种空值:
Nothing(异常)作为函数返回值其实是没有意义的,但是由于其可以作为所有类型的父类,因此可以用于丢出异常
def m2(n: Int): Int = {
if(n == 0)
throw new NullPointerException
else
return n
}
而Unit在全局只有一个实例。
由于scala包含了很多java的元素,其中与java的类型转换也有较大的差别。java中类型转换byte-short-int/char-int
由于scala是强类型语言,不同类型之间无法相互转换,因此就需要使用强制类型转换进行:
char c = 'a'
short c2 = c.toShort;
//直接 c = (short)c 会报错
一个要注意的一点是,虽然对于字符串我们可以拼接各种各样的基本数据类型,但是对于short、char这些类型的计算操作是需要我们乖乖转化为int的
scala在比较运算符中有一点的要注意的是,java中引用类型的的==,比较的是引用地址而在scala中比较的是值。(使用.eq来比较引用地址)
scala的位运算与其他语言基本一致,需要注意的是移动运算符«»为有符号的移动运算符,而«<»>是无符号的移动运算符。scala的运算符底层是方法所以可以通过如下方法调用
var n1 : Int = 12
println(n1.+(2))
scala中的分支语句可以像函数一样具有返回值,所以就可以写作:
val res : Any = if (a < 1){
println(a)
}else if(a > 1){
"6"
}else{
6
}
val res2 = if(a<1) "<" else ">"
在下面的这种写法下其实非常接近三元表达式。
scala的for循环类似python。
for(i <- 1.to(3))
for(i <- 1 to 3)
for(i <- new Range(1,10,3))
for(i <- 1.until(3))
for(i <- 1 until 3)
如果将for和if结合一下就可以得到混沌的循环守卫(scala没有continue)
for(i<-1.to(5) if i!= 2){
println(i);
}
虽然有很多可有可无的东西,但是其多层循环设计的非常合理:
for(i<- 1 to 4;j <- 1 to 5)
从前面的代码中可以看到scala可以获取if语句的返回值,同理也可以使用for循环的返回值,但是for循环默认返回的值是一个空的unit,若想获得for的返回值,需要将其变为一个list或array,这里需要使用到yield关键字
val b = for(i <- 1 to 10) yield i
由于相较于for循环,while非常的鸡肋,所以不如使用for。
对于scala,是没有break的,所以需要使用一个break类进行
import scala.util.control.Breaks._ //引入所有的
Breaks.breakable(
for(i<-0 until 5){
if (i == 3)
Breaks.break()
println(i)
}
)
scala除了面向对象以外,它还具有函数式编程的特性,函数的设计方式和python大同小异
def f1(str1: String*)
def f2(str1: String, str2: String*)
def f3(str1: String = "")
def f4(str1: String, int2: Int)
f4(int2=22,str1="")
scala的返回值和函数设计则是参考了多种语言的特性
其他的东西可能并不算太大的重点,核心的一个是lambda匿名函数的定义和使用:
val fun = (name : String) => {println(name)}
def f(func: String => Unit) : Unit = {
func("666")
}
总体来看,使用lambda函数的例子:
val add = (a: Int, b: Int) => a + b
val minus = (a: Int, b: Int) => a - b
def dualFunc(func:(Int, Int) => Int): Int = {
func(1, 2)
}
scala的函数式过于混沌:
def arrayOperation(array: Array[Int], op: Int=>Int): Array[Int] = {
for (elem <- array) yield op(elem)
}
看个练习:
def func(a:Int) : String => (Char => Boolean) = {
def f1(b: String): Char => Boolean= {
def f2(c: Char): Boolean = {
if (a == 0 && b == "" && c == '0') false else true
}
f2
}
f1
}
println(func(0)("")('0'))
def func(a: Int): String => (Char => Boolean) = {
b => c => if (a == 0 && b == "" && c == '0') false else true
}
//柯里化
def func(a: Int)(b: String)(c: Char): Boolean = {
if (a == 0 && b == "" && c == '0') false else true
}
scala对闭包有着较大的支持。同时也有函数柯里化的操作
scala还有一个比较有趣的东西叫做控制抽象,里面主要包含了传值参数和传名参数。其中传值参数很好理解:
f1(f2())
但是传名参数就很抽象了
def f2(a: => Int): Unit = {
println(a)
}
上面f2的参数是一个返回值为Int的代码块。每次调用a都会执行代码块中的内容。
最后再来看一个包含了上面所有内容的代码块
def myWhile(condition: => Boolean): ={
def doLoop(op: =>Unit):Unit = {
if(condition){
op
myWhile(condition)(op)
}
}
doLoop _
}
n=10
myWhile(n>=1){
println(n)
n-=1
}
//柯里化
def myWhile(condition: => Boolean)(op: =>Unit):Unit = {
if(condition){
op
myWhile(condition)(op)
}
}
对于python而言,惰性运算是内部存在定义的,只有需要取值时才会进行运算和操纵。而对于scala,只需要使用lazy关键字进行定义即可。
scala使用package定义包,其中可以直接使用包对象,包对象的定义必须和包定义在同一级目录下
scala的类拥有访问权限等内容,但是同样是老东西了。对于类的构造,只需要在定义类的时候添加形参即可,但是这只不过是主构造器,为了使类构造器可以实现重载等功能,可以使用this作为函数名设计一系列辅助构造器