在Scala里,下划线(_)可以表示函数值的参数。如果某个参数在函数里仅使用一次,就可以用下划线表示。每次在函数里用下划线,都表示随后的参数。

val arr = Array(1, 2, 3, 4, 5)
println("Sum of all values in array is " + (0 /: arr) { (sum, elem) => sum + elem })

上面的代码里使用了“/:”方法。这个方法的意思大致上是从数组的左侧开始迭代运算。这里是用来计算数组中所有元素的和。因为在函数值中sum和elem只用了一次,所以这个函数也可以这样写:

val arr = Array(1, 2, 3, 4, 5)
println("Sum of all values in array is " + (0 /: arr) {_+_} )

其中第一个“_”就是sum,即用来迭代运算的值;第二个“_”表示的是数组中的元素。这里是一处让人比较纠结的地方,是要简洁还是要可读性都得自己选择了(这次我偏向于简洁,因为熟悉scala以后理解这里应该不是问题)。如果能在不失可读性又足够简洁的地方使用就最好了,来看一下下面的例子:

val negativeNumberExists = arr.exists { _ < 0 }
println("Array has negative number? " + negativeNumberExists)

这里的代码用来查找数组中是否有小于0的元素。

在某些有意义的地方,这种简洁还可以更进一步。比如说我们想从一个数组中找出最大值。从这个需求出发,我们会一步步地简化实现的函数。最开始是这个样子的,我们使用了“/:”方法:

def max(a: Int, b: Int) = {
if (a > b)
a
else
b
}
println("Max value in array is " + (Int.MinValue /: arr) { (large, ele) => max(large, ele) })

用下划线表示函数值参数来做一次简化:

println("Max value in array is " + (Int.MinValue /: arr) { max(_, _) })

“_”不仅可以表示一个参数,还可以表示整个参数列表。这样的话就可以简化成这样:

println("Max value in array is " + (Int.MinValue /: arr) { max _ })

在上面的代码里,“_”表示整个参数列表。如果只是把参数传递给下层的方法(拿的原文,有疑义,什么是下层的方法),甚至可以省下使用“_”。上面的代码可以简化为:

println("Max value in array is " + (Int.MinValue /: arr) { max })

可以看到,依赖类型推断,scala的简洁到了丧心病狂(无贬义)的程度。这也给开发者留下了一个难题:需要适当克制自己简化代码的欲望,留下适当的可读性,不让代码变成天书。

################

scala学习手记27 - 下划线与参数的更多相关文章

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

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

  2. 六、Django学习之基于下划线的跨表查询

    六.Django学习之基于下划线的跨表查询 一对一 正向查询的例子为 已知用户名,查询用户的电话号码.反向查询例子反之. 正向查询 其中下划线前的表示表名,无下划线的表示的是Author表 resul ...

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

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

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

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

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

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

  6. scala学习手记36 - 容器基础

    scala的容器包括Set.List和Map.三种容器的特征和Java中一样.scala为每种容器都提供了可变和不可变两种版本,分别位于scala.collection.mutable或scala.c ...

  7. scala学习手记12 - 字段、方法和构造函数

    在上一节创建了一个scala类,如果没有更多的方法,scala类的定义还可以更简单一些,看一下下面这个CreditCard类的定义: class CreditCard(val number: Int, ...

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

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

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

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

随机推荐

  1. delphi弹出信息框大全(转载)

    1. 警告信息框 MessageBox(Handle,'警告信息框','警告信息框',MB_ICONWARNING); 2.疑问信息框 MessageBox(Handle,'疑问信息框','疑问信息框 ...

  2. TADDConnetion组件,TADOQuery

    一.TADDConnetion 二.TADOQuery 1.RecNo:从1开始 当前记录行数;ADOQuery1.RecNo 选择后一行数据集内容:ADOQuery1.RecNo:=ADOQuery ...

  3. Scalable IO in Java

    Scalable IO in Java http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf 大部分IO都是下面这个步骤, Most have same basi ...

  4. CNI插件实现框架---以loopback为示例

    以最简单的loopback插件作为实例,来分析CNI plugin的执行流程 // cni/plugins/loopback/loopback.go 1.func main() main函数只是简单地 ...

  5. python并发编程知识点总结

    1.到底什么是线程?什么是进程? Python自己没有这玩意,Python中调用的操作系统的线程和进程. 2.Python多线程情况下: 计算密集型操作:效率低,Python内置的一个全局解释器锁,锁 ...

  6. C++之(::)运算符详解

    ::运算符 (::)是运算符中等级最高的,作用有三种,都是左关联的,都是为了更明确自己调用的对象或者函数: 全局作用域 类作用域 命名空间作用域 1.全局作用域 #include<iostrea ...

  7. keras 学习文档

    https://github.com/fchollet/keras-resources https://keras.io/

  8. phpcms使用session的方法

    phpcms使用session //session开始 必须有下面的代码,否则无效 private function _session_start() { $session_storage = 'se ...

  9. 转:[NHibernate]视图处理

    转自:http://www.cnblogs.com/wolf-sun/p/4082899.html 目录 写在前面 文档与系列文章 视图 一个例子 总结 写在前面 前面的文章主要讲了对物理数据表的操作 ...

  10. eclipse添加tomcat运行时

    方法一:添加jar包 方法二配置依赖 比如缺少javax.servlet.http.HttpServlet,ctrol+shift+t查找这个包 <dependencies> <de ...