ego*_*doe 7 scala function-composition
我想要实现的是将 2 个函数(其中一个是没有 arg 函数)合二为一。
这是一个示例,可以让您了解我在做什么:
object Test extends App {
val zeroArgFunc = () => 10
val intArgFunc = (i: Int) => s"hello $i"
val stringArgFunc = (s: String) => println(s)
// This line works perfectly fine.
val intAndThenString: Int => Unit = stringArgFunc compose intArgFunc
// But this line fails with 'type mismatch' compilation error.
val zeroAndThenInt: () => String = intArgFunc compose zeroArgFunc
}
Run Code Online (Sandbox Code Playgroud)
编译错误:
[error] found : () => Int
[error] required: ? => Int
[error] val zeroAndThenInt: () => String = intArgFunc compose zeroArgFunc
[error] ^
[error] one error found
Run Code Online (Sandbox Code Playgroud)
知道出了什么问题吗?
[UPD] Scala 版本是 2.13.1(如果重要的话)。
脱糖() => 10我们有
new Function0[Int] { def apply() = 10 }
Run Code Online (Sandbox Code Playgroud)
并且Function0没有compose或andThen方法
trait Function0[... +R] extends ... { ...
def apply(): R
override def toString(): String = "<function0>"
}
Run Code Online (Sandbox Code Playgroud)
所以它似乎Function0无法组成。
另一方面(i: Int) => s"hello $i",(s: String) => println(s)对应于Function1哪个确实compose定义了方法,因此它们可以组合。
考虑更改() => 10为(_: Unit) => 10which 将类型从 更改Function0为Function1,然后
(intArgFunc compose zeroArgFunc)()
Run Code Online (Sandbox Code Playgroud)
输出res4: String = hello 10。
解决@Duelist 的评论,恕我直言,Function0[T]在语义上不等同于Function1[Unit, T]. 例如,给定
val f = () => 10
val g = (_: Unit) => 10
Run Code Online (Sandbox Code Playgroud)
然后
f()
g()
Run Code Online (Sandbox Code Playgroud)
确实输出
res7: Int = 10
res8: Int = 10
Run Code Online (Sandbox Code Playgroud)
然而
f(println("woohoo")) // error: no arguments allowed for nullary method apply
g(println("woohoo")) // OK!
Run Code Online (Sandbox Code Playgroud)
我们看到两者没有相同的行为。尽管如此,如果您想将它们视为等效的,也许您可以定义一个扩展方法Function0并明确转换,例如
implicit class Fun0ToFun1[A, B](f: () => A) {
def toFun1: Unit => A = (_: Unit) => f()
}
Run Code Online (Sandbox Code Playgroud)
将允许以下语法
(intArgFunc compose zeroArgFunc.toFun1)()
Run Code Online (Sandbox Code Playgroud)
通过@egordoe寻址评论,外的开箱compose只为过定义Function1,因此Function2,Function3等等,不能组成一样Function0。但是我们可以定义扩展composeN的功能的方法,例如,假设我们要组成Function1有Function0,然后
implicit class ComposeFun1WithFun0[A, B](f1: A => B) {
def compose0(f2: () => A): () => B = () => f1(f2())
}
Run Code Online (Sandbox Code Playgroud)
给
(intArgFunc compose0 zeroArgFunc)()
Run Code Online (Sandbox Code Playgroud)