`
kdlan
  • 浏览: 12787 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Programming in Scala 2nd 读书笔记 2

阅读更多
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)


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics