scala学习手记23 - 函数值
scala的一个最主要的特性就是支持函数编程。函数是函数编程中的一等公民:函数可以作为参数传递给其他函数,可以作为其他函数的返回值,甚至可以在其它函数中嵌套。这些高阶函数称为函数值。
举一个简单的例子:从1到某个数求和。使用Java很容易实现:
int sum(int max){
int result = 0;
for (int i = 0; i <= max; i++) {
result +=i;
}
return result;
}
使用scala实现也没有多大区别。
现在再扩展下需求:对某个范围内的奇数或偶数求和。使用java该怎么办呢,最直接的方式分别为奇数和偶数求和写一套方案就行了。但是这样纯粹重复的体力工作好像有些招人烦。此时如果能把奇偶分析的逻辑作为参数传递进来肯定是极好的。看看是如何使用函数式的方案来进行实现的:
def totalOverRange(max: Int, func: Int => Int): Int = {
var result = 0;
for (i <- 1 to max) {
result += func(i)
}
result
}
这里定义了一个totalOverRange函数来进行计算,这个函数有两个参数max和func。其中max是一个普通参数,表示循环的最大值。func则是一个函数值,其本质上是一个函数,接收一个Int并返回一个Int。在totalOverRange的方法体里,循环值的逻辑处理交由函数值func来实现,totalOverRange只负责累计。
先来试一下从1到max的简单求和:
print(totalOverRange(5, i=>i))
上面的代码段在调用totalOverRange方法时传递了两个参数,第一个参数标识循环到5,第二个参数“i=>i”则是一个匿名函数(也就是只有实现没有名字的函数),用来表示对循环值的处理逻辑。在函数中使用“=>”将左侧的参数列表和函数实现分开。这里的函数实现只是简单地将参数i返回。需要注意的是这里不需要指定函数值参数的类型,scala会从totalOverRange方法中推断出参数的类型。看一下执行结果:

再来做一下对5以内的偶数求和:
print(totalOverRange(5, i => if (i % 2 == 0) i else 0))
一开始我是这样写函数值的:
i => if (i % 2 == 0) return i else return 0
添加了return,但是这样做是错误的。不明白为什么,希望稍后的学习中可以解惑。
看一下执行结果:

奇数运算的逻辑就不需要我写了。
使用函数值的一个好处在这里已经显示出来了:可以减少代码的重复。将公共代码放到一个函数里,将差异的部分封装为函数值参数传递进去,从而减少代码的重复。这样子看起来是有些类似于模板方法模式的,不过不需要定义那么多的接口和类而已。
再想一下,如果作为函数值的函数很复杂该怎么办呢?是使用函数方案还是模板模式方案?
我也不好说,具体情况再具体分析吧。
#######
scala学习手记23 - 函数值的更多相关文章
- scala学习手记28 - Execute Around模式
我们访问资源需要关注对资源的锁定.对资源的申请和释放,还有考虑可能遇到的各种异常.这些事项本身与代码的逻辑操作无关,但我们不能遗漏.也就是说进入方法时获取资源,退出方法时释放资源.这种处理就进入了Ex ...
- scala学习手记26 - 重用函数值
函数值对消除代码重复有很大的帮助.但是像函数值这样直接将一个函数作为另一个函数的参数却不太利于函数值本身的重用. 来看一个例子: class Equipment(val routine: Int =& ...
- scala学习手记24 - 多参数函数值
上一节的函数值只有一个参数.函数值当然也是可以有多个参数的.看一下下面的inject方法: def inject(arr: Array[Int], initial: Int, operation: ( ...
- scala学习手记38 - 方法命名约定和for表达式
方法命名约定 之前在学习<运算符重载>一节时曾经说过一个方法命名约定:方法的第一个字符决定了方法的优先级.现在再说另一个命名约定:如果方法以冒号(:)结尾,则调用目标是运算符后面的实例. ...
- scala学习手记39 - 模式匹配
在java中有switch/case这样的模式匹配语句,可以匹配的类型包括int,byte,char,short, enum,在java8又支持了字符串. 在scala中也有类似的模式匹配语句,即ma ...
- scala学习手记37 - 容器的使用
这次统一看一下scala中容器类的几个方法. Set filter()方法 filter()方法用来从Set中过滤获取含有指定特征的元素.示例代码如下: val colors1 = Set(" ...
- scala学习手记30 - 闭包
首先要弄白闭包的概念. 教材中的说法是:闭包是一种特殊的函数值,闭包中封闭或绑定了在另一个作用域或上下文中定义的变量.这里说闭包是一种特殊的函数值. 维基百科中的说法是:在计算机科学中,闭包(英语:C ...
- scala学习手记27 - 下划线与参数
在Scala里,下划线(_)可以表示函数值的参数.如果某个参数在函数里仅使用一次,就可以用下划线表示.每次在函数里用下划线,都表示随后的参数. val arr = Array(1, 2, 3, 4, ...
- scala学习手记17 - 容器和类型推断
关于scala的类型推断前面已经提到过多次.再来看一下下面这个例子: import java.util._ var list1: List[Int] = new ArrayList[Int] var ...
随机推荐
- HDU 3367 Pseudoforest(Kruskal)
Pseudoforest Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) To ...
- node.js开发学习一HelloWorld
前言:由于公司业务需求,最近启动了node.js的开发任务,想把自己的开发学习历程记录记录下来,可以增加记忆,也方便查找.虽然对javascript有一定的了解,但是刚接触node.js的时候,发现还 ...
- 如何看懂ORACLE执行计划
如何看懂Oracle执行计划 一.什么是执行计划 An explain plan is a representation of the access path that is taken when a ...
- access variables from the global scope 在全局范围内访问变量的2种方法
w http://php.net/manual/zh/language.variables.scope.php http://php.net/manual/en/language.variables. ...
- 2015-03-10——简析javascript对象
对于构造函数,它是Function对象的一个实例,可以定义自己的静态成员先实例化出对象,后执行function中内部代码 静态成员: var abc = function () {}; //既是一 ...
- OpenSSL和https原理
https原理: 浏览器请求服务端的公钥证书,server将注冊的证书发送给client. client向办法机构验证证书的合法性,证书 包含公钥,server网址及一些信息. 验证完成,client ...
- beego——构造查询
QueryBuilder提供了一个简单.流畅的SQL查询构造器.在不影响代码可读性的前提下用来快速的建立SQL语句. QueryBuilder在功能上与ORM重合,但是个由利弊,ORM更适合用于简单的 ...
- Java面向对象—继承
概述: 1.多个类相同的属性和功能抽取成另一个类, 让具有特有功能的类继承这个类. 2.通过 extends 关键字可以实现类与类的继承 格式: class 子类名 extends 父类名 {} 特点 ...
- UVALive 6915 J - Leveling Ground
思路: 简单模拟下.从左向右扫描一次,求出挖出该区间空地的花费,并取个最小值即可. 至于怎么求区间内的高度最小值,就用线段树就好了. #include <bits/stdc++.h> #d ...
- Calendar的那些神坑
参考我的博客:http://www.isedwardtang.com/2017/08/31/java-calendar-bug/