Scala函数式程序设计原理 week1 Getting Started + Functions & Evaluation

来源:互联网 发布:单片机的蓝牙模块 编辑:程序博客网 时间:2024/06/05 20:09

求值策略

两种策略

Scala中有两种求值策略,一种叫做calll by name一种叫做call by value。两种策略会规约成相同的最终值,只要满足

  • 规约表达式由纯函数组成
  • 两者求值过程能够终止(不存在无限循环)

终止性质

当不满足终止条件时

  • 如果CBV能够终止,那么CBN也能够终止
  • 反之不成立
    Scala中通常使用call-by-name,如果函数参数的类型以=>开头,则表明使用call-by-name。
def constOne(x:Int,y:Int => Int) = 1

条件表达式

Scala中的if-else是表达式,由有值。每个表达式都有一个类型,表达式的类型是两个公共分支的超类型。
如果else部分缺失了,

if (x>0) 1

那么可能if语句没有输出值,解决办法是引入一个Unit类,写作()。等同于

if (x>0) 1 else ()

可以把()当作”无有用值”的占位符,将Unit当作void。(从技术上讲void没有值但是Unit有一个表示”无值”的值)

声明值和变量

val被定义时即被取值
lazy val在首次使用时取值
def在每一次被使用时取值

返回值类型

递归函数需要显式地指明返回值的类型,非递归函数的返回值类型是可选的。

块表达式

{}块包含一系列表达式,其结果也是一个表达式。块中最后一个表达式的值就是块的值。
在Scala中,赋值动作本身是没有值得,严格地说他们得值是Unit类型的,写作()
由于赋值语句的值是Unit类型,不要把他们串联在一起。

x = y = 1 //别这样做

可见性

块表达式内部的定义只能内部可见。内部的定义会遮蔽外部的同名定义。

分号和中缀运算符

Scala中,行尾的分号是可选的。
一行中有多个语句,每个语句用分号分隔。
当要多行表达式的时候,可以卸载括号内。

(someLongExp+somOtherExp)

或者可以在第一行写操作符,因为这告诉编译器表达式还未结束

someLongExp + someOtherExp

尾递归

如果一个函数在最后一步操作中调用自身,那么函数调用栈空间可以被重复使用。这叫做尾递归
尾递归是迭代过程
在Scala中,只有直接递归调用自身是可以被优化的。
使用@tailrec注解可以要求函数是尾巴递归的

@tailrecdef gcd(a: Int,b: Int): Int = ...

如果gcd的实现不是尾递归的,会报错。

参考资料

Scala函数式程序设计原理 week1
《快学Scala 第一版》

原创粉丝点击