Build-in Control Structure
for的声明里跟上if可以直接过滤符合条件的元素到for循环体里调用
多级的for循环可以直接在for里面声明
多级循环
{}内的语句会自动推断分号的位置
()里必须写清楚分号
for的声明后跟上yield会将for声明里符合条件的元素重新返回成为一个Array
不过函数式风格的编程里是没有for循环的,一般是用递归实现
多使用自带的foreach之类的接口
match 类似java的switch
但是不需要在每个case后面跟break;
默认的case 使用_
函数式编程里不要使用break和continue
虽然scala提供了机制可以使用
不过最好忘了他
Functions and Closures
可以在方法体内定义新的方法提高代码可读性和代码重用,避免满屏的私有方法
函数对象的声明
val func=(x: Int) => x + 1
向一些方法中传递的函数也基本上是上面类似的格式
scala> someNumbers.filter(x => x > 0)
也可以写成
scala> someNumbers.filter(_> 0)
直接使用_替代
多参数使用多个_,参数顺序同_的顺序
def sum(a: Int, b: Int, c: Int) = a + b + c
val b = sum(1, _: Int, 3)
b(2)
上面这个感觉有点闭包的意思
不定参数的声明
java中使用...
scala中使用* def echo(args: String*)
方法调用时(包括构造方法)可以指明参数的名称
如 def speed(distance: Float, time: Float): Float
调用时 speed(distance = 100, time = 10)
参数默认值
尾部递归调用会被编译器优化为循环实现,要求比较严格
Control Abstraction
对于一些模板代码,通过传递函数来实现不一样的部分(对比java的模板方法模式,继承和传递接口实现,实在是方便太多了)
object FileMatcher {
private def filesHere = (new java.io.File(".")).listFiles
private def filesMatching(matcher: String => Boolean) =
for (
file <filesHere;
if matcher(file.getName)
) yield file
def filesEnding(query: String) =
filesMatching(_.endsWith(query))
def filesContaining(query: String) =
filesMatching(_.contains(query))
def filesRegex(query: String) =
filesMatching(_.matches(query))
}
代码实现时尽量简化client调用的代码
Currying(咖喱棒?不知道怎么翻译)
类似数学里有f(x,y),先给定x的值,然后拿出去再给定y的值
有几种实现方式,最直观的
def curriedSum(x: Int)(y: Int) = x + y
val onePlus = curriedSum(1)_
onePlus(2)
自定义的控制结构实现需要用到currying的特性
def withPrintWriter(file: File)(op: PrintWriter => Unit) {
val writer = new PrintWriter(file)
try {
op(writer)
} finally {
writer.close()
}
}
val file = new File("date.txt")
withPrintWriter(file) {
writer => writer.println(new java.util.Date)
}
上面和java 1.7里try with resource的结构非常像
这个代码实现还有个好处,client不需要关注文件是否关闭了,减少代码冗余
接受空参数函数对象的声明
def myAssert(predicate: () => Boolean)
上面这个在调用时必需写成
myAssert(()=>5>3)
需要声明为
def byNameAssert(predicate: => Boolean)
调用时才可以写成
byNameAssert(5>3)