2. Higher Order Functions
把其他函数作为参数或者作为返回值,就是 higher order functions,python 里面也可以看到这样使用的情形。在酷壳上的博客有一个例子就是将函数作为返回值。
2.1 匿名函数
在 python 里边叫 lambda 函数,常常与 map(), filter(), reduce() 联合使用,前面也写过一篇这样的博客。
举一个 scala 的 reduce 的例子,f: Int => Int
表示 f 是一个整数映射到整数的函数,计算下面公式:
def sum(f: Int => Int, a: Int, b: Int): Int = {
def loop(a: Int, acc: Int): Int =
if (a > b) acc
else loop(a + 1, f(a) + acc)
loop(a, 0)
}
def sumInts(a: Int, b: Int) = sum(x => x, a, b) // f(n)=n
def sumCubes(a: Int, b: Int) = sum(x => x * x * x, a, b) // f(n)=n*n*n
println(sumInts(2, 7)) //求和
println(sumCubes(3, 10)) //求立方和
2.2 currying
把一个函数的多个参数分解成多个函数, 然后把函数多层封装起来,每层函数都返回一个函数去接收下一个参数这样,可以简化函数的多个参数。
// sum 返回函数 sumF,风格与 python 相似
def sum(f: Int => Int): (Int, Int) => Int = {
def sumF(a: Int, b:Int): Int =
if (a > b) 0 else f(a) + sumF(a + 1, b)
sumF
}
def sumInts = sum(x => x)
def sumCubes = sum(x => x * x * x)
sumInts(1, 5) //> res0: Int = 15
sumCubes(1, 5) //> res1: Int = 225
sum(x=>x)(1, 5) //> res2: Int = 15
(sum(x=>x))(1, 5) //> res3: Int = 15
更为简短的写法:
def sum(f: Int => Int)(a: Int, b: Int): Int =
if (a > b) 0 else f(a) + sum(f)(a + 1, b)
sum(x => x)(1, 5) // 第一个()相当于创建了一个匿名函数
mapReduce 实现过程包括 map 一一映射函数和 reduce 函数及单位元素 zero(乘为1,加为0),参数包括序列区间 [a, b] 两个参数,假设我们求 [a, b] 区间上所有元素的平方和:
def mapReduce(map: Int => Int, reduce: (Int, Int) => Int, zero: Int)(a: Int, b: Int): Int =
if (a > b) zero
else reduce(map(a), mapReduce(map, reduce, zero)(a + 1, b))
def sumOfSquare(a: Int, b: Int) = mapReduce(x => x*x, (x, y) => x + y, 0)(a, b) //这里确定了三个,留下参数a,b
比如求立方和,四次方和等,更灵活的用法是 map 和 reduce 可以先指定一个reduce(都是sum),使用时再指定另一个(map),代码就不贴了。总之,所有mapreduce设置,包括map,reduce, zero, a, b都可以无序设置,替换组合成包含不同参数列表的新函数。
2.3 类
构造一个分数(rational)类,实现加减、比大小等基本功能。
object rationals {
val x = new Rational(1, 3) //> x : week3.Rational = 1/3
val y = new Rational(5, 7) //> y : week3.Rational = 5/7
val z = new Rational(3) //> z : week3.Rational = 3/1
x.numer //> res0: Int = 1
x.sub(y).sub(z) //> res1: week3.Rational = 71/-21
y.add(y) //> res2: week3.Rational = 10/7
x.less(y) //> res3: Boolean = true
x.max(y) //> res4: week3.Rational = 5/7
}
class Rational(x: Int, y: Int) {
require(y != 0, "denomitor must be nonzero")
// scala 的构造函数就是执行body
def this(x: Int) = this(x, 1) // 第二种构造函数, 补全到第一种
private def gcd(a: Int, b: Int): Int =
if (b==0) a else gcd(b, a % b) //private函数,求最大公约数
val numer = x / gcd(x, y) // 每次构造新类,都化简
val denom = y / gcd(x, y) // val,gcd函数只计算一次
def add(that: Rational) =
new Rational(
numer * that.denom + denom * that.numer, // 交叉相乘相加
denom * that.denom)
def neg: Rational = new Rational(-numer, denom)
def sub(that: Rational) = add(that.neg)
def less(that: Rational) = numer * that.denom < that.numer * denom
def max(that: Rational) = if (this.less(that)) that else this // this 关键字,表示使用该method的object
override def toString = numer + "/" + denom // 每次打印类的格式
}
2.4 操作符
c++里面有操作符的重载,在scala里面技术层面上来说没有操作符这个概念。比如 1 + 2
实际是 1.+(2)
。 + 是对象 1 的一种方法。Scala 实现 1 + 2
这种写法需要两种技术,以上面的例子来分析:
- 上面的例子中
r.add(s)
可以写成r add s
,任何只包含一个参数的方法都可以写成这样的形式,这种做法叫Infix Notation。 - 但问题是,现在整数的加法是
a + b
,分数的加法如果是a add b
,风格不一致。还有一个方法叫 Relaxed Identifiers。大概意思是标志符不仅可以是字母开头的字符串组成,还可以是运算符(如果后面是冒号,加至少一个空格,否则会将冒号也看出标志的一部分)。
实现与整数加法风格一致的分数运算,代码如下:
package week3
object rationals {
val x = new Rational(1, 3) //> x : week3.Rational = 1/3
val y = new Rational(5, 7) //> y : week3.Rational = 5/7
val z = new Rational(3) //> z : week3.Rational = 3/1
-x //> res0: week3.Rational = 1/-3
x - y - z //> res1: week3.Rational = 71/-21
y + y //> res2: week3.Rational = 10/7
x < y //> res3: Boolean = true
x * x + z * z //> res4: week3.Rational = 82/9
}
class Rational(x: Int, y: Int) {
require(y != 0, "denomitor must be nonzero")
def this(x: Int) = this(x, 1)
private def gcd(a: Int, b: Int): Int =
if (b==0) a else gcd(b, a % b)
val numer = x / gcd(x, y)
val denom = y / gcd(x, y)
def + (that: Rational) =
new Rational(
numer * that.denom + denom * that.numer,
denom * that.denom)
def unary_- : Rational = new Rational(-numer, denom) // unary_:一元运算符和二元运算符不同,一元要特地指出
def - (that: Rational) = this + -that
def < (that: Rational) = numer * that.denom < that.numer * denom
def * (that: Rational) = new Rational(numer * that.numer, denom * that.denom)
override def toString = numer + "/" + denom // 打印类的格式
}
注意到上面代码中 x*x + z*z
没用括号也能计算出准确的结果,这是因为 scala 通用一套根据标识符确定运算优先级的规则表。
http://www.cnblogs.com/daniel-D/p/3812795.html
相关推荐
这本书所讲授的,正是基于 Scala 的函数式编程基础。基于 Scheme、Haskell 等老牌函数式语言的传统教材的问题在于,相关语言的语法和思维方式与读者现有的知识体系迥异,容易造成较为陡峭的入门门槛。此外,由于...
函数式编程基础 函数式编程说明 函数定义/声明 函数运行机制 递归 函数注意事项和细节 过程 惰性函数和异常 面向对象编程初级 类和对象 包 包对象 面向对象编程中级 封装 继承 多态 面向对象编程高级 ...
如果你粗略浏览Scala的网站,你会觉得Scala是一种纯粹的面向对象编程语言,而又无缝地结合了命令式编程和函数式编程风格。Christopher Diggins认为: 不太久之前编程语言还可以毫无疑意地归类成“命令式”或者...
快学Scala课后习题答案,包含各个章节答案word版和pdf版
第17讲-Scala编程详解:函数式编程之集合操作 共9页 第18讲-Scala编程详解:模式匹配 共11页 第19讲-Scala编程详解:类型参数 共13页 第20讲-Scala编程详解:隐式转换与隐式参数 共9页 第21讲-Scala编程详解:Actor...
从原有的面向对象编程(OO)到函数式编程(FP)的思想。本书面向实际的使用场景,提供了大量的Scala实例,同时,也给出底层的原理和相关的参考。对于Scala新手来说这是一本不错的入门书,对于老手来说也是一本夯实...
本书循序渐进地介绍了Scala的函数式编程基础,虽然篇幅短小,却切中要害。读者可以学会使用Scala静态语言的强大功能创建简洁、可扩展、高度可并行的代码。对于多核时代JVM上的并发编程,Scala是绝好的工具,而本书是...
函数式编程基础.pptx 面向对象编程(基础部分).pptx 面向对象编程(中级部分).pptx 面向对象编程(高级特性).pptx 隐式转换和隐式参数.pptx 集合(上)-基本使用.pptx 集合(下)-应用操作.pptx 模式匹配.pptx 函数式编程...
第17讲-Scala编程详解:函数式编程之集合操作 共9页 第18讲-Scala编程详解:模式匹配 共11页 第19讲-Scala编程详解:类型参数 共13页 第20讲-Scala编程详解:隐式转换与隐式参数 共9页 第21讲-Scala编程详解:Actor...
第17讲-Scala编程详解:函数式编程之集合操作 共9页 第18讲-Scala编程详解:模式匹配 共11页 第19讲-Scala编程详解:类型参数 共13页 第20讲-Scala编程详解:隐式转换与隐式参数 共9页 第21讲-Scala编程详解:Actor...
第17讲-Scala编程详解:函数式编程之集合操作 共9页 第18讲-Scala编程详解:模式匹配 共11页 第19讲-Scala编程详解:类型参数 共13页 第20讲-Scala编程详解:隐式转换与隐式参数 共9页 第21讲-Scala编程详解:Actor...
【课程列表】 2.1 Scala语言概述 2.2 Scala基础 2.3 面向对象编程基础 2.4 函数式编程基础
scala是一种基于JVM的面向对象的函数编程,scala编程相对于...2:函数式编程,柯里化函数,匿名函数,高阶函数等。 3:代码行简单。 4:支持并发控制,Actor Model机制 5:目前比较流行的kafka,spark均由scala开发。
第17讲-Scala编程详解:函数式编程之集合操作 共9页 第18讲-Scala编程详解:模式匹配 共11页 第19讲-Scala编程详解:类型参数 共13页 第20讲-Scala编程详解:隐式转换与隐式参数 共9页 第21讲-Scala编程详解:Actor...
第17讲-Scala编程详解:函数式编程之集合操作 共9页 第18讲-Scala编程详解:模式匹配 共11页 第19讲-Scala编程详解:类型参数 共13页 第20讲-Scala编程详解:隐式转换与隐式参数 共9页 第21讲-Scala编程详解:Actor...
第17讲-Scala编程详解:函数式编程之集合操作 共9页 第18讲-Scala编程详解:模式匹配 共11页 第19讲-Scala编程详解:类型参数 共13页 第20讲-Scala编程详解:隐式转换与隐式参数 共9页 第21讲-Scala编程详解:Actor...
基础:Scala中的函数式编程基础是一门全面的,自定进度的在线课程,没有任何先决条件,可帮助您成为自信,高效和强大的函数式Scala开发人员
第17讲-Scala编程详解:函数式编程之集合操作 共9页 第18讲-Scala编程详解:模式匹配 共11页 第19讲-Scala编程详解:类型参数 共13页 第20讲-Scala编程详解:隐式转换与隐式参数 共9页 第21讲-Scala编程详解:Actor...
第01阶段 :Scala 入门 第02阶段:Scala 的函数式编程 第03阶段:Scala 的面向对象编程 第04阶段:Scala的高级基础一 第05阶段:Scala的高级基础二
第8章,“函数和闭包”,深度讨论了函数式语言的基础建设模块,函数。 ...... 第31章,“组合子解析”,显示了如何使用Scala的解析器组合子库来创建解析器。 第32章,“GUI编程”,展示了使用Scala库简化基于Swing的...