• 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函数。

  • 相关阅读:
    Xamarin.FormsShell基础教程(3)Shell项目构成
    Xamarin.FormsShell基础教程(2)创建Shell解决方案
    Xamarin.Forms Shell基础教程(1)
    点击按钮,返回顶部
    三角形(css3)
    改变字体大小的媒体查询代码封装
    将毫秒格式化为分钟和秒 ,并补0
    节流函数
    打乱数组方法
    css使用总结
  • 原文地址:https://www.cnblogs.com/taich-flute/p/6507335.html
Copyright © 2020-2023  润新知