我要实现的是将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没有composeandThen方法

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定义,因此Function2Function3等,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/

10-11 17:11