我要实现的是将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
}
编译错误:
[error] found : () => Int
[error] required: ? => Int
[error] val zeroAndThenInt: () => String = intArgFunc compose zeroArgFunc
[error] ^
[error] one error found
知道有什么问题吗?
[UPD] Scala版本为2.13.1(如果需要的话)。
最佳答案
脱糖() => 10
new Function0[Int] { def apply() = 10 }
并且
Function0
没有compose
或andThen
方法trait Function0[... +R] extends ... { ...
def apply(): R
override def toString(): String = "<function0>"
}
因此看来
Function0
无法组成。另一方面,
(i: Int) => s"hello $i"
和(s: String) => println(s)
对应于确实定义了Function1
方法的compose
,因此可以组成它们。考虑将
() => 10
更改为(_: Unit) => 10
,这会将类型从Function0
更改为Function1
,然后(intArgFunc compose zeroArgFunc)()
输出
res4: String = hello 10
。IMHO
Function0[T]
通过@Duelist进行评论,在语义上不等同于Function1[Unit, T]
。例如,给定val f = () => 10
val g = (_: Unit) => 10
然后
f()
g()
确实输出
res7: Int = 10
res8: Int = 10
然而
f(println("woohoo")) // error: no arguments allowed for nullary method apply
g(println("woohoo")) // OK!
在这里我们看到两者没有相同的行为。但是,如果您想将它们视为等效的,则可以在
Function0
上定义扩展方法,并明确地进行转换,例如implicit class Fun0ToFun1[A, B](f: () => A) {
def toFun1: Unit => A = (_: Unit) => f()
}
将允许以下语法
(intArgFunc compose zeroArgFunc.toFun1)()
用@egordoe来评论,开箱即用的
compose
只为Function1
定义,因此Function2
,Function3
等,cannot就像Function0
一样组成。但是,我们可以在函数上定义扩展composeN
方法,例如,说我们要用Function1
组成Function0
,然后implicit class ComposeFun1WithFun0[A, B](f1: A => B) {
def compose0(f2: () => A): () => B = () => f1(f2())
}
给
(intArgFunc compose0 zeroArgFunc)()
关于scala - 如何编写零参数函数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59247372/