利用Scala高阶函数减少代码重复

理念

所有的函数都可以分为通用部分和非通用部分。通用部分每次调用都相同,非通用部分在不同的调用中可能有变化。通用部分就是函数体的静态代码,非通用部分通过参数来表达。如果把函数作为参数,那么函数所代表的算法逻辑,也可以作为非通用部分,从而整个函数的扩展性进一步增强,可以面向逻辑进行扩展。

Scala支持将函数作为参数传递,这给了我们更多优化代码的空间。把函数作为参数的函数,称为高阶函数。

实践

以一个文件搜索匹配的代码为例,优化之前的代码如下

def filesHere = new File("./src/main/scala").listFiles()

//查询已.scala结尾的文件
def filesEnding(query: String) = {
  for (file <- filesHere if file.getName.endsWith(query))
    yield file
}

//查询文件名包含关键字的
def filesContains(query: String) = {
  for (file <- filesHere if file.getName.contains(query))
    yield file
}

//按正则匹配查找文件
def filesRegex(query: String) = {
  for (file <- filesHere if file.getName.matches(query))
    yield file
}

可以发现,三个方法的大部分逻辑都是相同的,只有判断是否满足条件的逻辑有变化。因此,根据代码扩展的理念,我们接下来把这部分作为一个扩展点,用参数化的函数来表达,从而三个方法可以抽象成以下结构

def filesMatch(query: String) = {
  for (file <- filesHere if method(file.getName,query))
    yield file
}

其中的method就是我们要传入的函数参数,这个函数接收2个字符串,返回一个Boolean,具体的匹配逻辑,由每次传入的函数决定。因此,定一个一个通用的匹配框架代码,如下

//通用匹配代码
def filesMatch(query: String, isMatch: (String, String) => Boolean) = {
  for (file <- filesHere; if isMatch(file.getName, query))
    yield file
}

在不同的匹配方法中,只需要传入自己需要的匹配策略函数就可以了,因此,开始的3个匹配方法优化如下

def filesEnding(query: String) = {
  filesMatch(query, _.endsWith(_))
}

def filesContains(query: String) = {
  filesMatch(query, _.contains(_))
}

def filesRegex(query: String) = {
  filesMatch(query, _.matches(_))
}

通过上述方法,实现了通用和变化部分的解耦,减少了重复代码,增加了扩展性。

在此基础上,代码还可以进一步简化。filesMatch函数的调用者已经知道了query的内容,可以把query从filesMatch的参数中移除,从而代码优化如下

//通用匹配代码
def filesMatch(isMatch: (String) => Boolean) = {
  for (file <- filesHere; if isMatch(file.getName))
    yield file
}

def filesEnding(query: String) = {
  filesMatch(query, _.endsWith(query))
}

def filesContains(query: String) = {
  filesMatch(query, _.contains(query))
}

def filesRegex(query: String) = {
  filesMatch(query, _.matches(query))
}

//上面的_.endsWith(query)等函数,都是isMatch的字面量形式

这里就体现出闭包的作用,通过直接引用query这个自由变量,减少了1次参数传递。

小结

  1. 使用高阶函数优化代码的思路
    1. 找出重复和可变的代码
    2. 把可变部分的逻辑抽象成函数字面量表达式
    3. 使用的时候,以字面量的形式传入具体的函数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值