【问题标题】:Functional composition using for-comprehension results in Char instead of String使用 for-comprehension 的功能组合导致 Char 而不是 String
【发布时间】:2019-12-09 21:43:23
【问题描述】:

我试图用理解来构造我的对象调用,这是我的简单实现:

object FuncA extends (String => Int => String) {
    override def apply(str: String): Int => String = i => {
      s"${(str.toInt + i).toString}"
    }
  }

  object FuncB extends (String => Int) {
    override def apply(str: String): Int = {
      str.toInt
    }
  }

  for {
    funcAStr <- FuncA("1")(1)
    funcBStr <- FuncB(funcAStr) // Fails here
  } yield {
    println(s"Final String incremented as int is $funcBStr")
  }

但奇怪的是,我遇到了一个问题,即 funcAStr 被解释为 Char 而不是 String。任何理想为什么会这样?

【问题讨论】:

    标签: string scala functional-programming function-composition for-comprehension


    【解决方案1】:

    尽管包含for-loop 标签,但Scala 中的for 并未定义循环。 for 是定义mapflatMapwithFilter 调用序列的简写方式。

    你的代码翻译成这样:

    FuncA("1")(1).flatMap{ funcAStr =>
      FuncB(funcAStr).map{ funcBStr =>
        println(s"Final String incremented as int is $funcBStr")
      }
    }   
    

    Func("1")(1) 返回StringString 上的 flatMap 方法依次获取字符串的每个字符,所以 funcAStr 实际上是 Char 而不是 String

    【讨论】:

      【解决方案2】:

      像这样尝试使用andThen 的函数式组合

      (FuncA("1") andThen FuncB)(1)
      

      哪个输出

      res0: Int = 2
      

      【讨论】:

      • 我可以做到这一点,但我想坚持理解,因为我有很多想要编写的功能对象!
      【解决方案3】:

      在 Scala 中,for-comprehension 只是 flatMapmapforeach 嵌套调用的语法糖。简单来说,基本规则是每个箭头都将转换为嵌套的flatMap,最后一个箭头将转换为mapforeach,具体取决于您是否使用yield

      在您的情况下,for-comprehension 将转换为类似于:

      val r: Seq[Unit] = 
          FuncA("1")(1).flatMap{ funcAStr : Char =>
             FuncB(funcAStr).map{ funcBStr: Int =>
                 println(s"Final String incremented as int is $funcBStr")
             }
          }
      

      这并没有多大意义,因为首先funcBStr 期望String 而不是Char。但即使你修复了它,编译器也会抱怨,因为flatMap 会期望可以表示为GenTraversableOnce[B] 的东西。

      所以我猜你不应该在你的用例中使用 for-comprehension

      如果您使用 IntelliJ,您可以使用快捷键 Ctrl+Alt+D,这将显示 Desugar Scala 代码 对话框。然后您将能够选择 expand for comprehensions 并向您展示您的 for-comprehension 如何转换为 flatMap/map 调用。

      【讨论】:

        猜你喜欢
        • 2014-07-04
        • 2015-01-21
        • 1970-01-01
        • 1970-01-01
        • 2014-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-22
        相关资源
        最近更新 更多