scala中的函数组合特性

在Scala中,函数作为“一等公民”出现。可以通过使用函数可组合的特性,使得代码编写保持良好的DRY原则。以下示例:

 

1. Song类型,为歌曲名、歌手、热度等信息的封装。

case class Song(id: Long,
                name: String,
                singers: List[String],
                hot: Int) {


}

 

2. SongDemo1 ,存在代码重复

object SongDemo1 {
  type songFilter = Song => Boolean

  def findSingerSongs: Set[String] => songFilter =
    singerNames =>
      song => song.singers.exists(singerNames)

  def removeSingerSongs: Set[String] => songFilter =
    singerNames =>
      song => !song.singers.exists(singerNames)

  def fingTopHotSongs: Int => songFilter =
    hot =>
      song => song.hot >= hot

  def findLowHotSongs: Int => songFilter =
    hot =>
      song => song.hot < hot


  def main(args: Array[String]) {

    //过滤器,过滤掉歌手名为刘德华的歌曲.
    val exculdeSingerFilter = removeSingerSongs(Set("刘德华"))

  }
}

  在SongDemo1 中,定义了根据歌手名、热度过滤歌曲的几类过滤器,分别返回包含(不包含)指定歌手、热度大于(小于)给定值的歌曲列表。

可以发现,其中定义过滤器的代码有重复:(findSingerSongs、removeSingerSongs),(fingTopHotSongs、findLowHotSongs),不符合DRY原则。可以根据函数的组合特征进行改进:

3. SongDemo2 

object SongDemo2 {
  type SongFilter = Song => Boolean

  /**
    * 给定一个谓词函数predicate,返回和predicate对立的结果.
    *
    * @param predicate
    * @tparam T
    * @return
    */
  def reverse[T](predicate: T => Boolean) = (a: T) => !predicate(a)

  def findSingerSongs: Set[String] => SongFilter =
    singerNames =>
      song => song.singers.exists(singerNames)

  def removeSingerSongs = findSingerSongs.andThen(reverse(_))

  type HotChecker = Int => Boolean
  def hotFilter: HotChecker => SongFilter =
    f =>
      song => f(song.hot)

  def fingTopHotSongs: Int => SongFilter =
    hot =>
      hotFilter(_ >= hot)

  def findLowHotSongs: Int => SongFilter =
    hot =>
      hotFilter(_ < hot)


  def main(args: Array[String]) {

    //过滤器,过滤掉歌手名为刘德华的歌曲.
    val exculdeSingerFilter = removeSingerSongs(Set("刘德华"))

  }
}

  在SongDemo2 中,通过引入reverse函数(给定一个谓词函数predicate,返回和predicate对立的结果),

然后使用函数的可组合特性,重写removeSingerSongs 。

通过引入hotFilter函数(接收一个谓词函数,检查歌曲热度是否Ok,返回SongFilter类型),

进而使用hotFilter来表示fingTopHotSongs、findLowHotSongs函数。

 

posted on 2017-03-06 09:09  taich-flute  阅读(355)  评论(0编辑  收藏  举报

导航