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 - 函数值的更多相关文章

  1. scala学习手记28 - Execute Around模式

    我们访问资源需要关注对资源的锁定.对资源的申请和释放,还有考虑可能遇到的各种异常.这些事项本身与代码的逻辑操作无关,但我们不能遗漏.也就是说进入方法时获取资源,退出方法时释放资源.这种处理就进入了Ex ...

  2. scala学习手记26 - 重用函数值

    函数值对消除代码重复有很大的帮助.但是像函数值这样直接将一个函数作为另一个函数的参数却不太利于函数值本身的重用. 来看一个例子: class Equipment(val routine: Int =& ...

  3. scala学习手记24 - 多参数函数值

    上一节的函数值只有一个参数.函数值当然也是可以有多个参数的.看一下下面的inject方法: def inject(arr: Array[Int], initial: Int, operation: ( ...

  4. scala学习手记38 - 方法命名约定和for表达式

    方法命名约定 之前在学习<运算符重载>一节时曾经说过一个方法命名约定:方法的第一个字符决定了方法的优先级.现在再说另一个命名约定:如果方法以冒号(:)结尾,则调用目标是运算符后面的实例. ...

  5. scala学习手记39 - 模式匹配

    在java中有switch/case这样的模式匹配语句,可以匹配的类型包括int,byte,char,short, enum,在java8又支持了字符串. 在scala中也有类似的模式匹配语句,即ma ...

  6. scala学习手记37 - 容器的使用

    这次统一看一下scala中容器类的几个方法. Set filter()方法 filter()方法用来从Set中过滤获取含有指定特征的元素.示例代码如下: val colors1 = Set(" ...

  7. scala学习手记30 - 闭包

    首先要弄白闭包的概念. 教材中的说法是:闭包是一种特殊的函数值,闭包中封闭或绑定了在另一个作用域或上下文中定义的变量.这里说闭包是一种特殊的函数值. 维基百科中的说法是:在计算机科学中,闭包(英语:C ...

  8. scala学习手记27 - 下划线与参数

    在Scala里,下划线(_)可以表示函数值的参数.如果某个参数在函数里仅使用一次,就可以用下划线表示.每次在函数里用下划线,都表示随后的参数. val arr = Array(1, 2, 3, 4, ...

  9. scala学习手记17 - 容器和类型推断

    关于scala的类型推断前面已经提到过多次.再来看一下下面这个例子: import java.util._ var list1: List[Int] = new ArrayList[Int] var ...

随机推荐

  1. css 特殊处理样式记录

    1.解决任何盒子的垂直横向 居中显示 display: -webkit-box; -webkit-flex: 1; -webkit-box-orient: vertical; -webkit-box- ...

  2. easyui的datagrid无数据时下方滚动条不显示的解决办法(标题栏显示不完全)

    easyui在写datagrid的时候标题栏有时候因为太多.太长所以无法显示所有的列,而且没数据的时候下方的滚动条是不显示的,这样就无法显示所有的列了.解决办法如下: onLoadSuccess: f ...

  3. 剩余参数(rest arguments) Mixin

    Mixin – Pug 中文文档 https://pug.bootcss.com/language/mixins.html 混入 Mixin 混入是一种允许您在 Pug 中重复使用一整个代码块的方法. ...

  4. 第09章—使用Lombok插件

    spring boot 系列学习记录:http://www.cnblogs.com/jinxiaohang/p/8111057.html 码云源码地址:https://gitee.com/jinxia ...

  5. SQL与Access使用查询结果集更新表

    SQL语法 update 表1 set 字段1 = bb.字段1 from 表1 as aa, (select 字段1,字段2 from 表) bb where aa.字段2 = bb.字段2 Acc ...

  6. Css选择器定位详解

    1.使用 class 属性来定位元素,方法如下: driver.findElement(By.cssSelector("input.login")); 即可以先指定一个 HTML的 ...

  7. django博客项目1.环境搭建

    安装 Python Windows 下安装 Python 非常简单,去 Python 官方网站找到 Python 3 的下载地址,根据你的系统选择 32 位或者 64 位的安装包,下载好后双击安装即可 ...

  8. (3.8)常用知识-临时表、表变量、CTE的对比

    转自:https://www.cnblogs.com/xiaozhi1236/p/5895935.html 深入了解:https://www.cnblogs.com/kissdodog/archive ...

  9. android学习四---Activity和Intent

    1.android项目资源深入了解 在深入学习android之前,先好好玩玩手机上的应用,大部分程序都有一个图标,点开图标,程序启动,一定时间后,程序会跳转到第一个界面,比如手机QQ,点开图标,会跳出 ...

  10. Hive学习路线图--张丹老师

    前言 Hive是Hadoop家族中一款数据仓库产品,Hive最大的特点就是提供了类SQL的语法,封装了底层的MapReduce过程,让有SQL基础的业务人员,也可以直接利用Hadoop进行大数据的操作 ...