上一节的函数值只有一个参数。函数值当然也是可以有多个参数的。看一下下面的inject方法:

def inject(arr: Array[Int], initial: Int, operation: (Int, Int) => Int): Int = {
var carryOver = initial
arr.foreach(element => carryOver = operation(carryOver, element))
carryOver
}

在inject方法中有三个参数:一个数组、一个用来作为初始值的Int以及一个函数值。方法体也比较简单:遍历数组,使用数组元素参与函数值定义的操作。其中会将函数值操作结果取出再次参与运算。完成对数组的所有成员的运算后将结果返回。

看一下如何使用inject函数,如下演示了如何对数组元素求和:

val array = Array(2, 3, 5, 1, 6, 4)
val sum = inject(array, 0, (carryOver, elem) => carryOver + elem)
println("Sum of elements in array [" + array.mkString(",") + "] is " + sum)

inject()方法的第一个实参是一个数组,也就是想要求和的所有元素。第二个实参是求和的初始值0。第三个实参是执行元素求和操作的函数,一次一个。

输出如下:

执行数组求和可以,找出数组中的最大值也是可以的:

val array = Array(2, 3, 5, 1, 6, 4)
val sum = inject(array, array(0), (carryOver, elem) => Math.max(carryOver, elem))
println("Max of elements in array [" + array.mkString(",") + "] is " + sum)

输出如下:

实际上scala程序库已经内建了遍历数组的方法:foldLeft(),也是/:方法。下面是个例子,演示了如何使用/:方法执行上面的求和和找出最大值的操作:

val array = Array(2, 3, 5, 1, 6, 4)
val sum = (0 /: array) { (sum, elem) => sum + elem }
val max = (Integer.MIN_VALUE /: array) { (large, elem) => Math.max(large, elem) }
println("Sum of elements in array [" + array.mkString(",") + "] is" + sum)
println("Max of elements in array [" + array.mkString(",") + "] is" + max)

执行结果是:

不知道有没有注意到:这里在/:方法中使用函数值的方式与在inject方法中不一样——并没有将函数值作为参数,而是放到了花括号里。这并不表明inject方法也能这样使用。下面的代码就会报错:

val sum = inject(array, 0) {(carryOver, elem) => carryOver + elem}

报错信息如下:

这需要了解另一个概念:curry化。

下一节会说Curry化。

########

scala学习手记24 - 多参数函数值的更多相关文章

  1. scala学习手记30 - 闭包

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

  2. scala学习手记22 - 参数化类型的可变性

    java 的代码中多少有些不是很严谨的内容,比如下面的这段代码: public class Trouble { public static void main(String[] args) { Int ...

  3. scala学习手记23 - 函数值

    scala的一个最主要的特性就是支持函数编程.函数是函数编程中的一等公民:函数可以作为参数传递给其他函数,可以作为其他函数的返回值,甚至可以在其它函数中嵌套.这些高阶函数称为函数值. 举一个简单的例子 ...

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

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

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

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

  6. scala学习手记21 - 传递变长参数

    在Java中是可以使用变长参数的,如下面的方法: public void check(String ... args){ for(String tmp : args){ System.out.prin ...

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

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

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

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

  9. scala学习手记2 - scala中的循环

    先来看一段Java中的循环: for (int i = 1; i < 4; i++) { System.out.print(i + ","); } 毫无疑问,scala可以让 ...

随机推荐

  1. pre 布局

    w

  2. Squid 缓存代理服务器的完整配置

    Squid 缓存代理服务器 Squid 的作用 1.通过缓存的方式为用户提供web访问加速 2.对用户的web访问进行过滤控制 缓存代理服务器又分为普通代理服务器,透明代理服务器,和反向代理服务器. ...

  3. JS练习--自动生成100个li

    点击按钮,自动生成100个li,红.黄.蓝.绿四种颜色的顺序显示出现在页面中 CSS: ;;} ul,li{list-style: none;} #ul1{position: relative;} # ...

  4. 洛谷 P1641 [SCOI2010]生成字符串

    洛谷 这题一看就是卡塔兰数. 因为\(cnt[1] \leq cnt[0]\),很显然的卡塔兰嘛! 平时我们推导卡塔兰是用一个边长为n的正方形推的, 相当于从(0,0)点走到(n,n)点,向上走的步数 ...

  5. threading模块、ThreadLocal

    一.threading模块 1.线程对象的创建 1.1 Thread类直接创建 import threading import time def countNum(n): # 定义某个线程要运行的函数 ...

  6. 目标检测之R-FCN

    R-FCN:Object Detection via Region-based Fully Convolutional Networks R-FCN的网络结构 一个Base的convolutional ...

  7. 【Java编程】写入、读取、遍历Properties文件

    在Java开发中通常我们会存储配置參数信息到属性文件.这种属性文件能够是拥有键值对的属性文件,也能够是XML文件.关于XML文件的操作,请參考博文[Java编程]DOM XML Parser 解析.遍 ...

  8. Redis一(Redis-py与String操作)

    Redis 介绍 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(so ...

  9. MySQL读写分离之amoeba

    MySQL读写分离之amoeba主从复制的搭建环境参考:http://www.cnblogs.com/fansik/p/5270334.htmlamoeba依赖于jdk环境:jdk环境搭建参考:htt ...

  10. C++11中的array

    stl中的vector功能相比普通数据而言是要强大很多的,代价是需要动态的内存管理机制(分配,再分配,释放). 而有时候我们只需要普通的数组而已,这就带来了效率上的浪费. array就是用来代替普通的 ...