首页 > 解决方案 > 如何组成一个零参数函数?

问题描述

我想要实现的是将 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(如果重要的话)。

标签: scalafunction-composition

解决方案


脱糖() => 10我们有

new Function0[Int] { def apply() = 10 }

并且Function0没有composeorandThen方法

trait Function0[... +R] extends ... { ...
  def apply(): R
  override def toString(): String = "<function0>"
}

所以它似乎Function0无法组成。

另一方面(i: Int) => s"hello $i"(s: String) => println(s)对应于Function1哪个确实compose定义了方法,因此可以组合它们。

考虑更改() => 10to (_: Unit) => 10which 将类型从 更改Function0Function1,然后

(intArgFunc compose zeroArgFunc)()

输出res4: String = hello 10


解决@Duelist 的评论,恕我直言Function0[T],在语义上不等同于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不能Function0. 但是我们可以在函数上定义扩展composeN方法,例如,假设我们想用 组合Function1Function0那么

implicit class ComposeFun1WithFun0[A, B](f1: A => B) {
  def compose0(f2: () => A): () => B = () => f1(f2())
}

(intArgFunc compose0 zeroArgFunc)()

推荐阅读