zoukankan      html  css  js  c++  java
  • 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函数。

  • 相关阅读:
    人一生要去的100个地方(世界)
    数据仓库相关书籍
    学理财要看的书籍
    数仓设计 Building the Data Warehouse
    Google Cloud 安装java
    Google Cloud install python3 (in CentOS)
    SyntaxError: Non-ASCII character 'xe5' in file test23.py on line 2, but no encoding declared;
    CentOS 安装7z
    CentOS 安装 MySQL
    复杂迭代代码分析
  • 原文地址:https://www.cnblogs.com/taich-flute/p/6507335.html
Copyright © 2011-2022 走看看