scala学习笔记

4 篇文章 0 订阅
2 篇文章 0 订阅

《scala编程》学习笔记

推荐《scala编程》第三版(中文)。

相比python的疯狂封装,scala或许能让工程师更贴近源码编程。

一、一门可伸缩的语言

1、培育新类型

作为完全面向对象语言,scala可以为自定义的类提供类似内建的类型。比如,实现一个不会溢出的大数类型,其它语言也能做到,但scala可以做到这个BigInt就像scala自己提供的一样。

2、培育新的控制结构

很多语言都提供while控制结构,但都是在内建在语言级的。

虽然scala的while语句也是内建在语言内,但是利用提供的函数柯里化和极简原则可以编写自己的while结构。

// 自定义myWhile结构
def myWhile(isLoop: => Boolean)(opt: => Unit):Unit ={
    if(isLoop){
        opt
        myWhile(isLoop)(opt)
    }
}
// 使用自定义的myWhile结构
var n: Int = 10
myWhile(n>0){
    println(n)
    n -= 1
}

尽管while结构scala已经实现了,但我们也可以实现其它控制结构,就像原生支持的一样。《scala编程》的案例是并发编程Akka的控制结构,因为不利于理解,所以这里举了一个简单的例子。

二、为什么能可伸缩

1、scala是面向对象的

  1. scala的每个值都是对象,每个操作都是方法调用。比如1+2实际是在调用Int类里面定义的名为+的方法。而Java语言中的基本类型运算是语言自己定义的。
  2. 和其他语言相比,在组装对象方面,scala更为高级。比如,scala的特质,不但有抽象函数、还可以有方法实现甚至字段。
  3. 对象通过混入组合(mixin composition)构建,过程是取出某个类的所有成员,然后再加上若干特质的成员。类的不同维度的功能特性就可以被封装在不同的特质定义中。不同于多重继承(multiple inheritance)。
  4. 不像类,特质能够对某个未知的超类添加新的功能,这使得特质比类更为“可插拔”(pluggable)。
  5. 特质成功避开了多重继承中,当某个子类通过不同路径继承到同一个超类时产生的“钻石继承”(diamond inheritance)问题。

2、scala是函数式的

函数式编程以两大核心理念为指导。

1)函数是一等(first-class)的值

在函数式编程语言中,函数值的地位更整数、字符串等是相同的。可以将函数作为参数传递给其它函数,作为返回值返回它们,或者将它们保存在变量里。还可以在函数中定义另一个函数,就像在函数中定义整数那样。也可以在定义函数时不指定名字,就像整数字面量42,让函数字面量散落在代码中。

作为一等值的函数提供了对操作的抽象和创建新的控制结构的遍历。

2)程序中的操作应该将输入值映射成输出值,而不是当场(in place)修改数据

不可变数据结构时函数式编程的基石之一。scala提供了不可变的列表(list)、元组(tuple)、映射(map)、和集(set)等。

这个核心理念的另一种表述是方法不应该有副作用(side effect)。**方法只能通过接收入参和返回结果这两种方式与外部环境通信。**这种方法也被认为是“指称透明的”(referential transparent),意思是对于任何给定的输入,该方法调用都可以被其结果替换,同时不会影响程序的语义。

scala不强制要求不可变数据结构和指称透明的方法,但scala通常有其他更好的函数式的替代方案可供选择。

三、为什么要用scala

1、scala是兼容的

scala允许你对现有的Java代码增加价值。scala程序会被编译成JVM字节码,它们的运行期性能通常也跟Java程序相当。

scala代码可以调用java方法、访问Java字段、从Java类继承、实现Java接口。

scala支持隐式转换(implicit conversion),当类型没有正常匹配,或者代码中选中了(类型定义中)不存在的成员时,scala便会尝试可能的隐式转换。

2、scala是精简的

函数至简原则
  1. return可以省略,scala会使用函数体的最后一行作为返回值。
  2. 如果函数体只有一行代码,可以省略花括号。
  3. 返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)。
  4. 如果有return,则不能省略返回值类型,必须指定。
  5. 如果函数明确什么Unit,那么即使函数体中使用return关键字也不起作用。
  6. scala如果期望是无返回值类型,可以省略等号。
  7. 如果函数无参,但是声明了参数列表,那么调用时,小括号可加可不加。
  8. 如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略。
  9. 如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略。即匿名函数。

3、scala是高级的

// 假定name是String类型的
val nameHasUpperCase = name.exists(_.isUpper)

Java代码将字符串当作低级别的实体,在循环终逐个字符的遍历。

而scala代码将同样的字符串当作更高级别的字符序列(sequence),用前提(predicate)查询。

4、scala是静态类型的

静态的类型系统根据变量和表达式所包含和计算的值的类型来对它们进行归类。

scala不仅拥有跟Java类似的允许嵌套的类型系统,它还允许你用泛型(generics)来对类型进行参数化,用交集(intersection)来组合类型,以及用抽象类型(abstracttype)来隐藏类型的细节。

scala的类型系统解决了静态类型的两个常见的痛点:
  1. 通过类型推断规避了过于啰嗦的问题。
  2. 通过模式匹配以及其它编写和组合类型的新方式避免了死板。
静态类型系统的好处

1)可验证性质:静态类型系统可以证明某类运行期错误不可能发生。例如,它可以证明:

  1. 布尔值不能和整数相加;
  2. 私有变量不能从它们所属的类之外被访问;
  3. 函数调用时的入参个数不会错;
  4. 字符串的集只能添加字符串。

ps:测试只能证明错误存在,而不能证明没有错误——Edsger Dijkstra。

尽管静态类型带来的保障可能比较简单,但这是真正的保障,不是单元测试能够提供的。

1)安全的重构:静态类型系统提供了一个安全网,让你有十足的信心和把握对代码库进行修改。

  1. 假如要对方法添加一个额外的参数,可以执行修改、重新编译,然后简单的订正那些引起编译错误的代码行即可。一旦完成这些修改和订正,就能确信所有需要改的地方都改好了。
  2. 其它很多简单的重构也是如此,比如修改方法名,或者将方法从一个类挪到另一个类。

ps:在这些场景里,静态类型检查足以确保新系统会像老系统那样允许起来。

1)文档:静态类型时程序化的文档,编译器会检查其正确性。

  1. 类型标注永远不会过时(主要包含类型标注的源代码通过了编译)。
  2. 编译器和集成开发环境(IDE)也可以利用类型标注来提供更好的上下文相关的帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值