scala-startups

To be a good programer, I should Know about functional programming

What is Scala

Scala stands for Scalable language

Scala 融合了 面向对象 和 函数式 的特性。面向对象方便构建大型系统同时有利于拓展,而函数式对于处理有趣的功能点上能够快速的完成开发。(Scala’s functional programming constructs make it easy to build interesting things quickly from simple parts. Its object-oriented constructs make it easy to structure larger systems and to adapt them to new demands.)

关于scala应该包含什么类库

So the approach of attempting to provide
everything in one language doesn’t scale very well. Instead, Scala allows
users to grow and adapt the language in the directions they need by defining
easy-to-use libraries that feel like native language support.

从命令式到函数式的转变

这里不是说函数式就是灵丹妙药,而是旨在说明如果想学好和用好函数式编程,需要做出一些改变。首先需要识别什么样的风格是函数式风格:

One telltale sign is that if code contains any vars, it is probably in an imperative style. If the code contains no vars at all—i.e., it contains only vals—it is probably in a functional style.

如果要尽可能的用函数式的风格编程,可以尝试尽量少的使用变量(var),使用变量意味着函数可能会附带的产生某种副作用。

注意,这里提到的是var,也就是通常意义上的临时变量之类的。对于val这类不可变的变量不在此列

一开始会觉得,卧槽,不用变量怎么可能?不过可以考虑下是不是对问题的本质认识不清,所以无法使用更干净的方法实现。

来看下面一段代码的实现

def printArgs(args: Array[String]): Unit = {
    var i = 0
    while (i < args.length) {
        println(args(i))
        i += 1
    }
}

这里要实现一个打印参数的功能,如果这样用scala那真是抱着金砖哭穷啊。但是如果改成:

def printArgs(args: Array[String]): Unit = {
    args.foreach(println)
}

这样就不同了,不但消灭了变量,而且代码更简单,这意味着产生错误的可能性就减少了。所以如果函数式风格使用得当的话是能够让代码更简单,提高代码质量。

但是上面的代码还是存在副作用的可能,这是因为操作中涉及到了 output stream

The telltale sign of a function with side effects is that its result type is Unit. If a function isn’t returning any interesting value, which is what a result type of Unit means, the only way that function can make a difference in the world is through some kind of side effect.

上面的例子,更加函数式化的样式是

def formatArgs(args: Array[String]) = args.mkString("\n")

这样,处理参数的函数就消除了副作用。即便最后我们仍然需要使用outputstream,但是起码将这种副作用排除到了逻辑方法外。

从我们的编程经验中我们都知道有时候要消除副作用是困难的,因为真是世界总是千丝万缕的联系着,但是我们任然不能放弃消除副作用的机会。从上面的步骤实际上已经可以看出来如果消除副作用的方法,那就是:最小化副作用代码的作用域。最小化副作用代码另外还能方便我们进行测试,所以总体来说有两利无一害。

Scala is not a pure functional language that forces you to program
everything in the functional style. Scala is a hybrid imperative/functional language.

当然有时候你会发现命令式对处理手上的问题更有帮助,那么就不应该犹豫,漂亮的解决问题才是我们的目标(假设你是一个有良好品味的程序员的话(●’◡’●))。

说到了做好还是要强调,无论函数式还是命令式也好,只要能帮助写出漂亮易维护的代码的话就要采用之,不应该有某种派别或者宗教意识形态,这样才利于扩展我们的学识,不是吗?

基础问题记录

可变与不可变

Array 是可变的

List 是不可变的

Set 和 Map 同时又可变和不可变两种

immutable set 没有 += 方法, 但是 mutable set 有 += 方法,所以不可以在immutable set上调用 .+=(...)

Function

函数返回值,如果函数递归调用的话,必须在函数定义的时候显示的指明函数返回类型。

如果函数只有一个表达式,那么可以省略掉花括号({})

syntax of a function literal : (x: Int, y: Int) => x + y

方法名如果以 : 结尾,表示方法的参数可以放到方法左边,因此方法名也就到了操作数的右边,例如 List 的 :: 方法, 1 :: List 等价于 List.::(1)

Tuple

Tuple 的下标是从1 (xx._1)开始的,这是出于为了和首先使用tuple的语言保持一致

操作符

scala 不存在操作符重载的概念,因为scala中并不包含操作符,只不过我们可以使用*, +, -, / 等符号作为方法名

Higher-Order Function

也叫闭包。 可以理解为含有字段的Visitor

In functional programming, a visitor with fields is called a closure (or a higher-order function), which would be the result of applying a curried version of subst

—-A Little Java, A Few Patterns

Scala 的类型系统

Scala Hierarchy

类型的层次结构

Unit —> void in Java