使用 for-comprehension 的函数组合导致 Char 而不是 String
Functional composition using for-comprehension results in Char instead of String
我试图使用 for comprehension 来构造我的对象调用,这是我的简单实现:
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。任何理想这是为什么?
像这样使用 andThen
尝试功能组合
(FuncA("1") andThen FuncB)(1)
输出
res0: Int = 2
尽管包含 for-loop
标记,但 Scala 中的 for
并未定义循环。 for
是定义 map
、flatMap
和 withFilter
调用序列的 shorthand 方式。
您的代码转换为:
FuncA("1")(1).flatMap{ funcAStr =>
FuncB(funcAStr).map{ funcBStr =>
println(s"Final String incremented as int is $funcBStr")
}
}
Func("1")(1)
returnsString
。 String
上的 flatMap
方法依次获取字符串的每个字符,因此 funcAStr
实际上是 Char
而不是 String
.
在 Scala 中,for-comprehension 只是 flatMap
、map
或 foreach
嵌套调用的语法糖。简化一下,基本规则是每个箭头都将转换为嵌套的 flatMap
,最后一个箭头将转换为 map
或 foreach
,具体取决于您是否使用 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 Code 对话框。然后,您将能够 select 展开理解 并向您展示如何将 理解 转化为 flatMap
/map
调用。
我试图使用 for comprehension 来构造我的对象调用,这是我的简单实现:
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。任何理想这是为什么?
像这样使用 andThen
尝试功能组合
(FuncA("1") andThen FuncB)(1)
输出
res0: Int = 2
尽管包含 for-loop
标记,但 Scala 中的 for
并未定义循环。 for
是定义 map
、flatMap
和 withFilter
调用序列的 shorthand 方式。
您的代码转换为:
FuncA("1")(1).flatMap{ funcAStr =>
FuncB(funcAStr).map{ funcBStr =>
println(s"Final String incremented as int is $funcBStr")
}
}
Func("1")(1)
returnsString
。 String
上的 flatMap
方法依次获取字符串的每个字符,因此 funcAStr
实际上是 Char
而不是 String
.
在 Scala 中,for-comprehension 只是 flatMap
、map
或 foreach
嵌套调用的语法糖。简化一下,基本规则是每个箭头都将转换为嵌套的 flatMap
,最后一个箭头将转换为 map
或 foreach
,具体取决于您是否使用 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 Code 对话框。然后,您将能够 select 展开理解 并向您展示如何将 理解 转化为 flatMap
/map
调用。